ia64/xen-unstable

changeset 16285:a07288a84785

merge with xen-unstable.hg (staging)
author Alex Williamson <alex.williamson@hp.com>
date Tue Oct 30 15:34:44 2007 -0600 (2007-10-30)
parents c17bfb091790 7eb68d995aa7
children 42e032f52371
files buildconfigs/mk.linux-2.6-paravirt tools/check/check_libvncserver tools/check/check_sdl tools/xenfb/Makefile tools/xenfb/sdlfb.c tools/xenfb/vncfb.c tools/xenfb/xenfb.c tools/xenfb/xenfb.h xen/arch/ia64/vmx/mmio.c
line diff
     1.1 --- a/Config.mk	Tue Oct 30 11:33:55 2007 -0600
     1.2 +++ b/Config.mk	Tue Oct 30 15:34:44 2007 -0600
     1.3 @@ -89,7 +89,6 @@ ACM_SECURITY ?= n
     1.4  XENSTAT_XENTOP     ?= y
     1.5  VTPM_TOOLS         ?= n
     1.6  LIBXENAPI_BINDINGS ?= n
     1.7 -XENFB_TOOLS        ?= n
     1.8  PYTHON_TOOLS       ?= y
     1.9  
    1.10  -include $(XEN_ROOT)/.config
     2.1 --- a/Makefile	Tue Oct 30 11:33:55 2007 -0600
     2.2 +++ b/Makefile	Tue Oct 30 15:34:44 2007 -0600
     2.3 @@ -103,7 +103,7 @@ world:
     2.4  
     2.5  # clean doesn't do a kclean
     2.6  .PHONY: clean
     2.7 -clean:: 
     2.8 +clean::
     2.9  	$(MAKE) -C xen clean
    2.10  	$(MAKE) -C tools clean
    2.11  	$(MAKE) -C docs clean
    2.12 @@ -154,6 +154,11 @@ help:
    2.13  	@echo '  uninstall        - attempt to remove installed Xen tools'
    2.14  	@echo '                     (use with extreme care!)'
    2.15  	@echo
    2.16 +	@echo 'Trusted Boot (tboot) targets:'
    2.17 +	@echo '  build-tboot      - download and build the tboot module'
    2.18 +	@echo '  install-tboot    - download, build, and install the tboot module'
    2.19 +	@echo '  clean-tboot      - clean the tboot module if it exists'
    2.20 +	@echo
    2.21  	@echo 'Environment:'
    2.22  	@echo '  XEN_PYTHON_NATIVE_INSTALL=y'
    2.23  	@echo '                   - native python install or dist'
    2.24 @@ -194,8 +199,43 @@ uninstall:
    2.25  	rm -rf $(D)/usr/share/xen
    2.26  	rm -rf $(D)/usr/share/man/man1/xen*
    2.27  	rm -rf $(D)/usr/share/man/man8/xen*
    2.28 +	rm -rf $(D)/boot/tboot*
    2.29  
    2.30  # Legacy targets for compatibility
    2.31  .PHONY: linux26
    2.32  linux26:
    2.33  	$(MAKE) 'KERNELS=linux-2.6*' kernels
    2.34 +
    2.35 +
    2.36 +#
    2.37 +# tboot targets
    2.38 +#
    2.39 +
    2.40 +TBOOT_TARFILE = tboot-20071029.tar.gz
    2.41 +TBOOT_BASE_URL = http://downloads.sourceforge.net/tboot
    2.42 +
    2.43 +.PHONY: build-tboot
    2.44 +build-tboot: download_tboot
    2.45 +	$(MAKE) -C tboot build
    2.46 +
    2.47 +.PHONY: install-tboot
    2.48 +install-tboot: download_tboot
    2.49 +	$(MAKE) -C tboot install
    2.50 +
    2.51 +.PHONY: clean-tboot
    2.52 +clean-tboot:
    2.53 +	[ ! -d tboot ] || $(MAKE) -C tboot clean
    2.54 +
    2.55 +.PHONY: distclean-tboot
    2.56 +distclean-tboot:
    2.57 +	[ ! -d tboot ] || $(MAKE) -C tboot distclean
    2.58 +
    2.59 +.PHONY: download_tboot
    2.60 +download_tboot: tboot/Makefile
    2.61 +
    2.62 +tboot/Makefile: tboot/$(TBOOT_TARFILE)
    2.63 +	[ -e tboot/Makefile ] || tar -xzf tboot/$(TBOOT_TARFILE) -C tboot/ --strip-components 1
    2.64 +
    2.65 +tboot/$(TBOOT_TARFILE):
    2.66 +	mkdir -p tboot
    2.67 +	wget -O tboot/$(TBOOT_TARFILE) $(TBOOT_BASE_URL)/$(TBOOT_TARFILE)
     3.1 --- a/README	Tue Oct 30 11:33:55 2007 -0600
     3.2 +++ b/README	Tue Oct 30 15:34:44 2007 -0600
     3.3 @@ -1,13 +1,13 @@
     3.4 -#############################
     3.5 - __  __            _____  _ 
     3.6 - \ \/ /___ _ __   |___ / / |
     3.7 -  \  // _ \ '_ \    |_ \ | |
     3.8 -  /  \  __/ | | |  ___) || |
     3.9 - /_/\_\___|_| |_| |____(_)_|
    3.10 +#################################
    3.11 + __  __            _____  ____  
    3.12 + \ \/ /___ _ __   |___ / |___ \ 
    3.13 +  \  // _ \ '_ \    |_ \   __) |
    3.14 +  /  \  __/ | | |  ___) | / __/ 
    3.15 + /_/\_\___|_| |_| |____(_)_____|
    3.16 +                                
    3.17 +#################################
    3.18  
    3.19 -#############################
    3.20 -
    3.21 -http://www.xensource.com/xen/about.html
    3.22 +http://www.xen.org/
    3.23  
    3.24  What is Xen?
    3.25  ============
    3.26 @@ -21,7 +21,7 @@ development community, spearheaded by Xe
    3.27  by the original Xen development team to build enterprise products
    3.28  around Xen.
    3.29  
    3.30 -The 3.1 release offers excellent performance, hardware support and
    3.31 +The 3.2 release offers excellent performance, hardware support and
    3.32  enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and
    3.33  live relocation of VMs. This install tree contains source for a Linux
    3.34  2.6 guest; ports to Linux 2.4, NetBSD, FreeBSD and Solaris are
    3.35 @@ -55,8 +55,8 @@ 2. Configure your bootloader to boot Xen
    3.36     /boot/grub/menu.lst: edit this file to include an entry like the
    3.37     following:
    3.38  
    3.39 -    title Xen 3.1 / XenLinux 2.6
    3.40 -       kernel /boot/xen-3.1.gz console=vga
    3.41 +    title Xen 3.2 / XenLinux 2.6
    3.42 +       kernel /boot/xen-3.2.gz console=vga
    3.43         module /boot/vmlinuz-2.6-xen root=<root-dev> ro console=tty0
    3.44         module /boot/initrd-2.6-xen.img
    3.45  
    3.46 @@ -75,7 +75,7 @@ 2. Configure your bootloader to boot Xen
    3.47     32MB memory for internal use, which is not available for allocation
    3.48     to virtual machines.
    3.49  
    3.50 -3. Reboot your system and select the "Xen 3.1 / XenLinux 2.6" menu
    3.51 +3. Reboot your system and select the "Xen 3.2 / XenLinux 2.6" menu
    3.52     option. After booting Xen, Linux will start and your initialisation
    3.53     scripts should execute in the usual way.
    3.54  
    3.55 @@ -202,3 +202,29 @@ Xend (the Xen daemon) has the following 
    3.56      * For optional XenAPI support in XM, PyXML:
    3.57            URL:    http://pyxml.sourceforge.net
    3.58            YUM:    PyXML
    3.59 +
    3.60 +
    3.61 +Intel(R) Trusted Execution Technology Support
    3.62 +=============================================
    3.63 +
    3.64 +Intel's technology for safer computing, Intel(R) Trusted Execution Technology
    3.65 +(Intel(R) TXT), defines platform-level enhancements that provide the building
    3.66 +blocks for creating trusted platforms.  For more information, see
    3.67 +http://www.intel.com/technology/security/.
    3.68 +
    3.69 +Intel(R) TXT support is provided by the Trusted Boot (tboot) module in
    3.70 +conjunction with minimal logic in the Xen hypervisor.
    3.71 +
    3.72 +Tboot is an open source, pre- kernel/VMM module that uses Intel(R) TXT to
    3.73 +perform a measured and verified launch of an OS kernel/VMM.
    3.74 +
    3.75 +The Trusted Boot module is available from
    3.76 +http://sourceforge.net/projects/tboot.  This project hosts the code in a
    3.77 +mercurial repo at http://tboot.sourceforge.net/hg/tboot.hg and contains
    3.78 +tarballs of the source.  Instructions in the tboot README describe how
    3.79 +to modify grub.conf to use tboot to launch Xen.
    3.80 +
    3.81 +There are optional targets as part of Xen's top-level makefile that will
    3.82 +downlaod and build tboot: install-tboot, build-tboot, dist-tboot, clean-tboot.
    3.83 +These will download the latest tar file from the SourceForge site using wget,
    3.84 +then build/install/dist according to Xen's settings.
     4.1 --- a/buildconfigs/mk.linux-2.6	Tue Oct 30 11:33:55 2007 -0600
     4.2 +++ b/buildconfigs/mk.linux-2.6	Tue Oct 30 15:34:44 2007 -0600
     4.3 @@ -1,14 +1,10 @@
     4.4  XEN_LINUX_SOURCE ?= tarball
     4.5  LINUX_VER ?= 2.6
     4.6  
     4.7 -XEN_LINUX_TARBALL_KETCHUP := y
     4.8 -
     4.9  IMAGE_TARGET ?= vmlinux bzImage
    4.10  
    4.11 -XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    4.12 -
    4.13  XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
    4.14  
    4.15  EXTRAVERSION ?=
    4.16  
    4.17 -include buildconfigs/mk.linux-2.6-xen
    4.18 +include buildconfigs/mk.linux-2.6-common
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/buildconfigs/mk.linux-2.6-common	Tue Oct 30 15:34:44 2007 -0600
     5.3 @@ -0,0 +1,158 @@
     5.4 +LINUX_SERIES = 2.6
     5.5 +
     5.6 +# Linux search path, will be searched for tarballs and mercurial
     5.7 +# repositories.
     5.8 +LINUX_SRC_PATH ?= .:..
     5.9 +
    5.10 +# The source directory is not automatically updated to avoid blowing
    5.11 +# away developer's changes. If you want to automatically pull a new
    5.12 +# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make
    5.13 +# command line.
    5.14 +ifeq ($(XEN_LINUX_UPDATE),y)
    5.15 +__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update
    5.16 +else
    5.17 +__XEN_LINUX_UPDATE =
    5.18 +endif
    5.19 +
    5.20 +# Let XEN_TARGET_ARCH override ARCH.
    5.21 +ifeq ($(XEN_TARGET_ARCH),x86_32)
    5.22 +LINUX_ARCH	?= i386
    5.23 +else
    5.24 +LINUX_ARCH	?= $(XEN_TARGET_ARCH)
    5.25 +endif
    5.26 +
    5.27 +LINUX_DIR     = build-linux-$(LINUX_VER)$(EXTRAVERSION)_$(XEN_TARGET_ARCH)
    5.28 +
    5.29 +IMAGE_TARGET ?= vmlinuz
    5.30 +ifneq ($(XEN_TARGET_ARCH),ia64)
    5.31 +IMAGE_PATH ?= arch/$(LINUX_ARCH)/boot/$(firstword $(IMAGE_TARGET))
    5.32 +else
    5.33 +IMAGE_PATH ?= arch/ia64/hp/sim/boot/vmlinux.gz
    5.34 +endif
    5.35 +INSTALL_BOOT_PATH := $(DESTDIR)/boot
    5.36 +
    5.37 +LINUX_VER3  := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
    5.38 +
    5.39 +.PHONY: _build
    5.40 +_build: build
    5.41 +
    5.42 +include buildconfigs/src.$(XEN_LINUX_SOURCE)
    5.43 +
    5.44 +# Default to allowing interface mismatch
    5.45 +ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH
    5.46 +XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    5.47 +endif
    5.48 +
    5.49 +KERNELRELEASE = $(shell $(MAKE) -s --no-print-directory -C $(LINUX_DIR) kernelrelease)
    5.50 +
    5.51 +# The real action starts here!
    5.52 +.PHONY: build
    5.53 +build: $(LINUX_DIR)/include/linux/autoconf.h
    5.54 +ifneq ($(XEN_LINUX_ALLOW_INTERFACE_MISMATCH),y)
    5.55 +	@if ! diff -urN -X buildconfigs/interface.exclude \
    5.56 +              $(LINUX_SRCDIR)/include/xen/interface xen/include/public ; then \
    5.57 +		echo "" 1>&2 ; \
    5.58 +		echo " *** $(LINUX_SRCDIR)/include/xen/interface is out of date " 1>&2 ; \
    5.59 +		echo " *** relative to $(XEN_ROOT)/xen/include/public." 1>&2 ; \
    5.60 +		echo "" 1>&2 ; \
    5.61 +		exit 1 ; \
    5.62 +	fi
    5.63 +endif
    5.64 +	if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
    5.65 +	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
    5.66 +	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
    5.67 +	fi
    5.68 +	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) $(IMAGE_TARGET)
    5.69 +	mkdir -p $(INSTALL_BOOT_PATH)
    5.70 +	cp $(LINUX_DIR)/$(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE)
    5.71 +	cp $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE)
    5.72 +	cp $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE)
    5.73 +
    5.74 +$(LINUX_DIR)/include/linux/autoconf.h: CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
    5.75 +$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
    5.76 +	rm -rf $(LINUX_DIR)
    5.77 +	mkdir -p $(LINUX_DIR)
    5.78 +	# Re-use config from install dir if one exists. Next try to use
    5.79 +	# buildconfigs/create_config.sh is one is provided by the source
    5.80 +	# tree. Finally attempt to use make defconfig.
    5.81 +	set -e ; \
    5.82 +	CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p' $(LINUX_SRCDIR)/Makefile); \
    5.83 +	if [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \
    5.84 +	  cp $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) $(CONFIG_FILE) ; \
    5.85 +        elif [ -e $(LINUX_SRCDIR)/buildconfigs/create_config.sh ] ; then \
    5.86 +	  cd $(LINUX_SRCDIR) && sh buildconfigs/create_config.sh \
    5.87 +		$(CONFIG_FILE) $(EXTRAVERSION) $(XEN_TARGET_ARCH) $(XEN_SYSTYPE) ; \
    5.88 +          echo "Configured $(LINUX_DIR) using create_config.sh" ; \
    5.89 +	elif $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) defconfig O=$$(/bin/pwd)/$(LINUX_DIR) ; then \
    5.90 +	  echo "Configured $(LINUX_DIR) using defconfig" ; \
    5.91 +	else \
    5.92 +          echo "No configuration method found for this kernel" ; \
    5.93 +	fi
    5.94 +ifneq ($(XEN_LINUX_CONFIG_UPDATE),)
    5.95 +	echo "Updating $(CONFIG_FILE) using $(XEN_LINUX_CONFIG_UPDATE)"
    5.96 +	sh $(XEN_LINUX_CONFIG_UPDATE) $(CONFIG_FILE)
    5.97 +endif
    5.98 +ifeq ($(XEN_TARGET_ARCH),x86_32)
    5.99 +ifeq ($(pae),y)
   5.100 +	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)
   5.101 +else
   5.102 +	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
   5.103 +endif
   5.104 +endif
   5.105 +ifneq ($(EXTRAVERSION),)
   5.106 +	echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen
   5.107 +endif
   5.108 +	$(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR)
   5.109 +	@if [ ! -f $(LINUX_DIR)/Makefile ] ; then \
   5.110 +	    echo "***********************************"; \
   5.111 +	    echo "oldconfig did not create a Makefile"; \
   5.112 +	    echo "Generating $(LINUX_DIR)/Makefile   "; \
   5.113 +	    echo "***********************************"; \
   5.114 +	    ( echo "# Automatically generated: don't edit"; \
   5.115 +	      echo ""; \
   5.116 +	      echo "VERSION = 2"; \
   5.117 +	      echo "PATCHLEVEL = 6"; \
   5.118 +	      echo ""; \
   5.119 +	      echo "KERNELSRC    := $(CURDIR)/$(LINUX_SRCDIR)"; \
   5.120 +	      echo "KERNELOUTPUT := $(CURDIR)/$(LINUX_DIR)"; \
   5.121 +	      echo ""; \
   5.122 +	      echo "MAKEFLAGS += --no-print-directory"; \
   5.123 +	      echo ""; \
   5.124 +	      echo ".PHONY: all \$$(MAKECMDGOALS)"; \
   5.125 +	      echo ""; \
   5.126 +	      echo "all:"; \
   5.127 +	      echo "	\$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT)"; \
   5.128 +	      echo ""; \
   5.129 +	      echo "Makefile:;"; \
   5.130 +	      echo ""; \
   5.131 +	      echo "\$$(filter-out all Makefile,\$$(MAKECMDGOALS)) %/:"; \
   5.132 +	      echo "	\$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT) \$$@"; \
   5.133 +	    ) > $(LINUX_DIR)/Makefile ; \
   5.134 +	fi
   5.135 +	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) prepare
   5.136 +
   5.137 +.PHONY: prep
   5.138 +prep: $(LINUX_DIR)/include/linux/autoconf.h
   5.139 +
   5.140 +.PHONY: config
   5.141 +config: CONFIGMODE = menuconfig
   5.142 +config: $(LINUX_DIR)/include/linux/autoconf.h
   5.143 +	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
   5.144 +
   5.145 +.PHONY: clean
   5.146 +clean::
   5.147 +	[ ! -d $(LINUX_DIR) ] || \
   5.148 +		$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
   5.149 +
   5.150 +.PHONY: delete
   5.151 +delete: 
   5.152 +	rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR) $(LINUX_SRCDIR)
   5.153 +
   5.154 +.PHONY: mrproper
   5.155 +mrproper:
   5.156 +	rm -rf $(LINUX_SRCDIR)
   5.157 +	rm -f linux-$(LINUX_VER).tar.bz2
   5.158 +
   5.159 +.PHONY: $(LINUX_SRCDIR)/.force-update
   5.160 +$(LINUX_SRCDIR)/.force-update:
   5.161 +	@ :
     6.1 --- a/buildconfigs/mk.linux-2.6-native	Tue Oct 30 11:33:55 2007 -0600
     6.2 +++ b/buildconfigs/mk.linux-2.6-native	Tue Oct 30 15:34:44 2007 -0600
     6.3 @@ -2,6 +2,4 @@ EXTRAVERSION = -native
     6.4  IMAGE_TARGET = bzImage
     6.5  INSTALL_BOOT_PATH = $(DESTDIR)/boot
     6.6  
     6.7 -XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
     6.8 -
     6.9 -include buildconfigs/mk.linux-2.6-xen
    6.10 +include buildconfigs/mk.linux-2.6-common
     7.1 --- a/buildconfigs/mk.linux-2.6-paravirt	Tue Oct 30 11:33:55 2007 -0600
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,15 +0,0 @@
     7.4 -XEN_LINUX_SOURCE ?= tarball
     7.5 -XEN_LINUX_MIRROR ?= http://xenbits.xensource.com/ext/paravirt_ops/
     7.6 -LINUX_VER ?= 2.6-paravirt
     7.7 -
     7.8 -# This target currently only supports x86_32.
     7.9 -XEN_TARGET_ARCH = x86_32
    7.10 -IMAGE_TARGET ?= vmlinux bzImage
    7.11 -
    7.12 -XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    7.13 -
    7.14 -XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
    7.15 -
    7.16 -EXTRAVERSION ?= -paravirt
    7.17 -
    7.18 -include buildconfigs/mk.linux-2.6-xen
     8.1 --- a/buildconfigs/mk.linux-2.6-xen	Tue Oct 30 11:33:55 2007 -0600
     8.2 +++ b/buildconfigs/mk.linux-2.6-xen	Tue Oct 30 15:34:44 2007 -0600
     8.3 @@ -1,163 +1,6 @@
     8.4 -LINUX_SERIES = 2.6
     8.5 +EXTRAVERSION ?= -xen
     8.6  LINUX_VER    ?= 2.6.18
     8.7  
     8.8 -EXTRAVERSION ?= -xen
     8.9 -
    8.10 -# Linux search path, will be searched for tarballs and mercurial
    8.11 -# repositories.
    8.12 -LINUX_SRC_PATH ?= .:..
    8.13 -
    8.14 -# The source directory is not automatically updated to avoid blowing
    8.15 -# away developer's changes. If you want to automatically pull a new
    8.16 -# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make
    8.17 -# command line.
    8.18 -ifeq ($(XEN_LINUX_UPDATE),y)
    8.19 -__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update
    8.20 -else
    8.21 -__XEN_LINUX_UPDATE =
    8.22 -endif
    8.23 -
    8.24  XEN_LINUX_SOURCE ?= hg-clone
    8.25  
    8.26 -# Let XEN_TARGET_ARCH override ARCH.
    8.27 -ifeq ($(XEN_TARGET_ARCH),x86_32)
    8.28 -LINUX_ARCH	?= i386
    8.29 -else
    8.30 -LINUX_ARCH	?= $(XEN_TARGET_ARCH)
    8.31 -endif
    8.32 -
    8.33 -LINUX_DIR     = build-linux-$(LINUX_VER)$(EXTRAVERSION)_$(XEN_TARGET_ARCH)
    8.34 -
    8.35 -IMAGE_TARGET ?= vmlinuz
    8.36 -ifneq ($(XEN_TARGET_ARCH),ia64)
    8.37 -IMAGE_PATH ?= arch/$(LINUX_ARCH)/boot/$(firstword $(IMAGE_TARGET))
    8.38 -else
    8.39 -IMAGE_PATH ?= arch/ia64/hp/sim/boot/vmlinux.gz
    8.40 -endif
    8.41 -INSTALL_BOOT_PATH := $(DESTDIR)/boot
    8.42 -
    8.43 -LINUX_VER3  := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
    8.44 -
    8.45 -.PHONY: _build
    8.46 -_build: build
    8.47 -
    8.48 -include buildconfigs/src.$(XEN_LINUX_SOURCE)
    8.49 -
    8.50 -# Default to allowing interface mismatch
    8.51 -ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH
    8.52 -XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    8.53 -endif
    8.54 -
    8.55 -KERNELRELEASE = $(shell $(MAKE) -s --no-print-directory -C $(LINUX_DIR) kernelrelease)
    8.56 -
    8.57 -# The real action starts here!
    8.58 -.PHONY: build
    8.59 -build: $(LINUX_DIR)/include/linux/autoconf.h
    8.60 -ifneq ($(XEN_LINUX_ALLOW_INTERFACE_MISMATCH),y)
    8.61 -	@if ! diff -urN -X buildconfigs/interface.exclude \
    8.62 -              $(LINUX_SRCDIR)/include/xen/interface xen/include/public ; then \
    8.63 -		echo "" 1>&2 ; \
    8.64 -		echo " *** $(LINUX_SRCDIR)/include/xen/interface is out of date " 1>&2 ; \
    8.65 -		echo " *** relative to $(XEN_ROOT)/xen/include/public." 1>&2 ; \
    8.66 -		echo "" 1>&2 ; \
    8.67 -		exit 1 ; \
    8.68 -	fi
    8.69 -endif
    8.70 -	if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
    8.71 -	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
    8.72 -	    $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
    8.73 -	fi
    8.74 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) $(IMAGE_TARGET)
    8.75 -	mkdir -p $(INSTALL_BOOT_PATH)
    8.76 -	cp $(LINUX_DIR)/$(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE)
    8.77 -	cp $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE)
    8.78 -	cp $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE)
    8.79 -
    8.80 -$(LINUX_DIR)/include/linux/autoconf.h: CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
    8.81 -$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
    8.82 -	rm -rf $(LINUX_DIR)
    8.83 -	mkdir -p $(LINUX_DIR)
    8.84 -	# Re-use config from install dir if one exists. Next try to use
    8.85 -	# buildconfigs/create_config.sh is one is provided by the source
    8.86 -	# tree. Finally attempt to use make defconfig.
    8.87 -	set -e ; \
    8.88 -	CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p' $(LINUX_SRCDIR)/Makefile); \
    8.89 -	if [ -r $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \
    8.90 -	  cp $(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) $(CONFIG_FILE) ; \
    8.91 -        elif [ -e $(LINUX_SRCDIR)/buildconfigs/create_config.sh ] ; then \
    8.92 -	  cd $(LINUX_SRCDIR) && sh buildconfigs/create_config.sh \
    8.93 -		$(CONFIG_FILE) $(EXTRAVERSION) $(XEN_TARGET_ARCH) $(XEN_SYSTYPE) ; \
    8.94 -          echo "Configured $(LINUX_DIR) using create_config.sh" ; \
    8.95 -	elif $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) defconfig O=$$(/bin/pwd)/$(LINUX_DIR) ; then \
    8.96 -	  echo "Configured $(LINUX_DIR) using defconfig" ; \
    8.97 -	else \
    8.98 -          echo "No configuration method found for this kernel" ; \
    8.99 -	fi
   8.100 -ifneq ($(XEN_LINUX_CONFIG_UPDATE),)
   8.101 -	echo "Updating $(CONFIG_FILE) using $(XEN_LINUX_CONFIG_UPDATE)"
   8.102 -	sh $(XEN_LINUX_CONFIG_UPDATE) $(CONFIG_FILE)
   8.103 -endif
   8.104 -ifeq ($(XEN_TARGET_ARCH),x86_32)
   8.105 -ifeq ($(pae),y)
   8.106 -	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)
   8.107 -else
   8.108 -	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
   8.109 -endif
   8.110 -endif
   8.111 -ifneq ($(EXTRAVERSION),)
   8.112 -	echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen
   8.113 -endif
   8.114 -	$(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR)
   8.115 -	@if [ ! -f $(LINUX_DIR)/Makefile ] ; then \
   8.116 -	    echo "***********************************"; \
   8.117 -	    echo "oldconfig did not create a Makefile"; \
   8.118 -	    echo "Generating $(LINUX_DIR)/Makefile   "; \
   8.119 -	    echo "***********************************"; \
   8.120 -	    ( echo "# Automatically generated: don't edit"; \
   8.121 -	      echo ""; \
   8.122 -	      echo "VERSION = 2"; \
   8.123 -	      echo "PATCHLEVEL = 6"; \
   8.124 -	      echo ""; \
   8.125 -	      echo "KERNELSRC    := $(CURDIR)/$(LINUX_SRCDIR)"; \
   8.126 -	      echo "KERNELOUTPUT := $(CURDIR)/$(LINUX_DIR)"; \
   8.127 -	      echo ""; \
   8.128 -	      echo "MAKEFLAGS += --no-print-directory"; \
   8.129 -	      echo ""; \
   8.130 -	      echo ".PHONY: all \$$(MAKECMDGOALS)"; \
   8.131 -	      echo ""; \
   8.132 -	      echo "all:"; \
   8.133 -	      echo "	\$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT)"; \
   8.134 -	      echo ""; \
   8.135 -	      echo "Makefile:;"; \
   8.136 -	      echo ""; \
   8.137 -	      echo "\$$(filter-out all Makefile,\$$(MAKECMDGOALS)) %/:"; \
   8.138 -	      echo "	\$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT) \$$@"; \
   8.139 -	    ) > $(LINUX_DIR)/Makefile ; \
   8.140 -	fi
   8.141 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) prepare
   8.142 -
   8.143 -.PHONY: prep
   8.144 -prep: $(LINUX_DIR)/include/linux/autoconf.h
   8.145 -
   8.146 -.PHONY: config
   8.147 -config: CONFIGMODE = menuconfig
   8.148 -config: $(LINUX_DIR)/include/linux/autoconf.h
   8.149 -	$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
   8.150 -
   8.151 -.PHONY: clean
   8.152 -clean::
   8.153 -	[ ! -d $(LINUX_DIR) ] || \
   8.154 -		$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
   8.155 -
   8.156 -.PHONY: delete
   8.157 -delete: 
   8.158 -	rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR) $(LINUX_SRCDIR)
   8.159 -
   8.160 -.PHONY: mrproper
   8.161 -mrproper:
   8.162 -	rm -rf $(LINUX_SRCDIR)
   8.163 -	rm -f linux-$(LINUX_VER).tar.bz2
   8.164 -
   8.165 -.PHONY: $(LINUX_SRCDIR)/.force-update
   8.166 -$(LINUX_SRCDIR)/.force-update:
   8.167 -	@ :
   8.168 +include buildconfigs/mk.linux-2.6-common
     9.1 --- a/buildconfigs/mk.linux-2.6.5-SLES-xen	Tue Oct 30 11:33:55 2007 -0600
     9.2 +++ b/buildconfigs/mk.linux-2.6.5-SLES-xen	Tue Oct 30 15:34:44 2007 -0600
     9.3 @@ -2,8 +2,6 @@
     9.4  XEN_TARGET_ARCH = x86_32
     9.5  XEN_TARGET_X86_PAE = y
     9.6  
     9.7 -XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
     9.8 -
     9.9  EXTRAVERSION = -xen
    9.10  LINUX_VER = 2.6.5-SLES
    9.11  
    10.1 --- a/buildconfigs/mk.linux-2.6.9-RHEL-xen	Tue Oct 30 11:33:55 2007 -0600
    10.2 +++ b/buildconfigs/mk.linux-2.6.9-RHEL-xen	Tue Oct 30 15:34:44 2007 -0600
    10.3 @@ -2,8 +2,6 @@
    10.4  XEN_TARGET_ARCH = x86_32
    10.5  XEN_TARGET_X86_PAE = y
    10.6  
    10.7 -XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
    10.8 -
    10.9  EXTRAVERSION = -xen
   10.10  LINUX_VER = 2.6.9-RHEL
   10.11  
    11.1 --- a/buildconfigs/src.tarball	Tue Oct 30 11:33:55 2007 -0600
    11.2 +++ b/buildconfigs/src.tarball	Tue Oct 30 15:34:44 2007 -0600
    11.3 @@ -1,9 +1,6 @@
    11.4  XEN_LINUX_MIRROR ?= http://www.kernel.org/pub/linux/kernel/v2.6/
    11.5  XEN_LINUX_TARBALL ?= linux-$(LINUX_VER)-xen.tar.bz2
    11.6  
    11.7 -# Update using ketchup instead of manipulating tarball manually.
    11.8 -XEN_LINUX_TARBALL_KETCHUP ?= n
    11.9 -
   11.10  LINUX_SRCDIR ?= linux-$(LINUX_VER)
   11.11  
   11.12  KETCHUP ?= python buildconfigs/ketchup
   11.13 @@ -17,17 +14,6 @@ linux-%.tar.bz2:
   11.14  
   11.15  # XXX create a pristine tree for diff -Nurp convenience
   11.16  
   11.17 -ifeq ($(XEN_LINUX_TARBALL_KETCHUP),y)
   11.18  %/.valid-src: $(__XEN_LINUX_UPDATE)
   11.19  	$(KETCHUP) -d $(@D) $(LINUX_VER)
   11.20  	touch $@ # update timestamp to avoid rebuild
   11.21 -else
   11.22 -%/.valid-src: $(__XEN_LINUX_UPDATE) %.tar.bz2
   11.23 -	rm -rf tmp-linux-$* $(@D)
   11.24 -	mkdir -p tmp-linux-$*
   11.25 -	tar -C tmp-linux-$* -jxf $<
   11.26 -	-@rm -f tmp-linux-$*/pax_global_header
   11.27 -	mv tmp-linux-$*/* $(@D)
   11.28 -	@rm -rf tmp-linux-$*
   11.29 -	touch $@ # update timestamp to avoid rebuild
   11.30 -endif
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/docs/misc/vtd.txt	Tue Oct 30 15:34:44 2007 -0600
    12.3 @@ -0,0 +1,50 @@
    12.4 +Title   : How to do PCI Passthrough with VT-d
    12.5 +Authors : Allen Kay    <allen.m.kay@intel.com>
    12.6 +          Weidong Han  <weidong.han@intel.com>
    12.7 +Created : October-24-2007
    12.8 +Updated : October-24-2007
    12.9 +
   12.10 +How to turn on VT-d in Xen
   12.11 +--------------------------
   12.12 +
   12.13 +1 ) cd xen-unstable.hg
   12.14 +2 ) make install
   12.15 +3 ) make linux-2.6-xen-config CONFIGMODE=menuconfig
   12.16 +4 ) change XEN->"PCI-device backend driver" from "M" to "*".
   12.17 +5 ) make linux-2.6-xen-build
   12.18 +6 ) make linux-2.6-xen-install
   12.19 +7 ) depmod 2.6.18.8-xen
   12.20 +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
   12.21 +9 ) cp initrd-2.6.18-xen.img /boot
   12.22 +10) lspci - select the PCI BDF you want to assign to guest OS
   12.23 +11) "hide" pci device from dom0 as following sample grub entry:
   12.24 +
   12.25 +title Xen-Fedora Core (2.6.18-xen)
   12.26 +        root (hd0,0)
   12.27 +        kernel /boot/xen.gz com1=115200,8n1 console=com1 vtd=1
   12.28 +        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
   12.29 +        module /boot/initrd-2.6.18-xen.img
   12.30 +
   12.31 +12) reboot system
   12.32 +13) add "pci" line in /etc/xen/hvm.conf for to assigned devices
   12.33 +        pci = [ '01:00.0', '03:00.0' ]
   12.34 +15) start hvm guest and use "lspci" to see the passthru device and
   12.35 +    "ifconfig" to see if IP address has been assigned to NIC devices.
   12.36 +
   12.37 +
   12.38 +VT-d Enabled Systems
   12.39 +--------------------
   12.40 +
   12.41 +1) For VT-d enabling work on Xen, we have been using development
   12.42 +systems using following Intel motherboards:
   12.43 +    - DQ35MP
   12.44 +    - DQ35JO
   12.45 +
   12.46 +2) As far as we know, following OEM systems also has vt-d enabled.
   12.47 +Feel free to add others as they become available.
   12.48 +
   12.49 +- Dell: Optiplex 755
   12.50 +http://www.dell.com/content/products/category.aspx/optix?c=us&cs=555&l=en&s=biz
   12.51 +
   12.52 +- HP Compaq:  DC7800
   12.53 +http://h10010.www1.hp.com/wwpc/us/en/en/WF04a/12454-12454-64287-321860-3328898.html
    13.1 --- a/tools/Makefile	Tue Oct 30 11:33:55 2007 -0600
    13.2 +++ b/tools/Makefile	Tue Oct 30 15:34:44 2007 -0600
    13.3 @@ -20,7 +20,6 @@ SUBDIRS-y += xenstat
    13.4  SUBDIRS-y += libaio
    13.5  SUBDIRS-y += blktap
    13.6  SUBDIRS-y += libfsimage
    13.7 -SUBDIRS-$(XENFB_TOOLS) += xenfb
    13.8  SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
    13.9  
   13.10  # These don't cross-compile
    14.1 --- a/tools/check/Makefile	Tue Oct 30 11:33:55 2007 -0600
    14.2 +++ b/tools/check/Makefile	Tue Oct 30 15:34:44 2007 -0600
    14.3 @@ -7,7 +7,7 @@ all: build
    14.4  # Check this machine is OK for building on.
    14.5  .PHONY: build
    14.6  build:
    14.7 -	XENFB_TOOLS=$(XENFB_TOOLS) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY) ./chk build
    14.8 +	LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY) ./chk build
    14.9  
   14.10  # Check this machine is OK for installing on.
   14.11  # DO NOT use this check from 'make install' in the parent
   14.12 @@ -15,7 +15,7 @@ build:
   14.13  # copy rather than actually installing.
   14.14  .PHONY: install
   14.15  install:
   14.16 -	XENFB_TOOLS=$(XENFB_TOOLS) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY) ./chk install
   14.17 +	LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY) ./chk install
   14.18  
   14.19  .PHONY: clean
   14.20  clean:
    15.1 --- a/tools/check/check_libvncserver	Tue Oct 30 11:33:55 2007 -0600
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,38 +0,0 @@
    15.4 -#!/bin/sh
    15.5 -# CHECK-BUILD CHECK-INSTALL
    15.6 -
    15.7 -if [ ! "$XENFB_TOOLS" = "y" ]
    15.8 -then
    15.9 -    echo -n "unused, "
   15.10 -    exit 0
   15.11 -fi
   15.12 -
   15.13 -RC=0
   15.14 -
   15.15 -LIBVNCSERVER_CONFIG="$(which libvncserver-config)"
   15.16 -tmpfile=$(mktemp)
   15.17 -
   15.18 -if test -z ${LIBVNCSERVER_CONFIG}; then 
   15.19 -    RC=1
   15.20 -else
   15.21 -    ${LIBVNCSERVER_CONFIG} --libs 2>&1 > /dev/null
   15.22 -    RC=$?
   15.23 -fi
   15.24 -
   15.25 -if test $RC -ne 0; then
   15.26 -    echo "FAILED"
   15.27 -	echo " *** libvncserver-config is missing. "
   15.28 -    echo " *** Please install libvncserver."
   15.29 -elif ! ld $($LIBVNCSERVER_CONFIG --libs) -o $tmpfile >/dev/null 2>&1; then
   15.30 -    echo "FAILED"
   15.31 -    echo " *** dependency libraries for libvncserver are missing: "
   15.32 -    RC=1
   15.33 -    for i in $(ld $($LIBVNCSERVER_CONFIG --libs) -o $tmpfile 2>&1 >/dev/null); do
   15.34 -        case $i in
   15.35 -        -l*) echo lib${i#-l}
   15.36 -        esac
   15.37 -    done
   15.38 -fi
   15.39 -rm -f $tmpfile
   15.40 -
   15.41 -exit $RC
    16.1 --- a/tools/check/check_sdl	Tue Oct 30 11:33:55 2007 -0600
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,27 +0,0 @@
    16.4 -#!/bin/sh
    16.5 -# CHECK-BUILD CHECK-INSTALL
    16.6 -
    16.7 -if [ ! "$XENFB_TOOLS" = "y" ]
    16.8 -then
    16.9 -    echo -n "unused, "
   16.10 -    exit 0
   16.11 -fi
   16.12 -
   16.13 -RC=0
   16.14 -
   16.15 -SDL_CONFIG="$(which sdl-config)"
   16.16 -
   16.17 -if test -z ${SDL_CONFIG}; then 
   16.18 -    RC=1
   16.19 -else
   16.20 -    ${SDL_CONFIG} --libs 2>&1 > /dev/null
   16.21 -    RC=$?
   16.22 -fi
   16.23 -
   16.24 -if test $RC -ne 0; then
   16.25 -    echo "FAILED"
   16.26 -	echo " *** sdl-config is missing. "
   16.27 -    echo " *** Please install libsdl-dev or sdl."
   16.28 -fi
   16.29 -
   16.30 -exit $RC
    17.1 --- a/tools/console/daemon/io.c	Tue Oct 30 11:33:55 2007 -0600
    17.2 +++ b/tools/console/daemon/io.c	Tue Oct 30 15:34:44 2007 -0600
    17.3 @@ -35,6 +35,7 @@
    17.4  #include <termios.h>
    17.5  #include <stdarg.h>
    17.6  #include <sys/mman.h>
    17.7 +#include <sys/time.h>
    17.8  #if defined(__NetBSD__) || defined(__OpenBSD__)
    17.9  #include <util.h>
   17.10  #elif defined(__linux__) || defined(__Linux__)
   17.11 @@ -47,13 +48,20 @@
   17.12  /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
   17.13  #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
   17.14  
   17.15 +/* How many events are allowed in each time period */
   17.16 +#define RATE_LIMIT_ALLOWANCE 30
   17.17 +/* Duration of each time period in ms */
   17.18 +#define RATE_LIMIT_PERIOD 200
   17.19 +
   17.20  extern int log_reload;
   17.21  extern int log_guest;
   17.22  extern int log_hv;
   17.23  extern char *log_dir;
   17.24  
   17.25  static int log_hv_fd = -1;
   17.26 +static evtchn_port_or_error_t log_hv_evtchn = -1;
   17.27  static int xc_handle = -1;
   17.28 +static int xce_handle = -1;
   17.29  
   17.30  struct buffer
   17.31  {
   17.32 @@ -76,10 +84,12 @@ struct domain
   17.33  	char *serialpath;
   17.34  	int use_consolepath;
   17.35  	int ring_ref;
   17.36 -	evtchn_port_t local_port;
   17.37 -	evtchn_port_t remote_port;
   17.38 +	evtchn_port_or_error_t local_port;
   17.39 +	evtchn_port_or_error_t remote_port;
   17.40  	int xce_handle;
   17.41  	struct xencons_interface *interface;
   17.42 +	int event_count;
   17.43 +	long long next_period;
   17.44  };
   17.45  
   17.46  static struct domain *dom_head;
   17.47 @@ -377,6 +387,7 @@ int xs_gather(struct xs_handle *xs, cons
   17.48  static int domain_create_ring(struct domain *dom)
   17.49  {
   17.50  	int err, remote_port, ring_ref, rc;
   17.51 +	char *type, path[PATH_MAX];
   17.52  
   17.53  	err = xs_gather(xs, dom->serialpath,
   17.54  			"ring-ref", "%u", &ring_ref,
   17.55 @@ -393,6 +404,14 @@ static int domain_create_ring(struct dom
   17.56  	} else
   17.57  		dom->use_consolepath = 0;
   17.58  
   17.59 +	sprintf(path, "%s/type", dom->use_consolepath ? dom->conspath: dom->serialpath);
   17.60 +	type = xs_read(xs, XBT_NULL, path, NULL);
   17.61 +	if (type && strcmp(type, "xenconsoled") != 0) {
   17.62 +		free(type);
   17.63 +		return 0;
   17.64 +	}
   17.65 +	free(type);
   17.66 +
   17.67  	if ((ring_ref == dom->ring_ref) && (remote_port == dom->remote_port))
   17.68  		goto out;
   17.69  
   17.70 @@ -483,6 +502,13 @@ static struct domain *create_domain(int 
   17.71  {
   17.72  	struct domain *dom;
   17.73  	char *s;
   17.74 +	struct timeval tv;
   17.75 +
   17.76 +	if (gettimeofday(&tv, NULL) < 0) {
   17.77 +		dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
   17.78 +		      __FILE__, __FUNCTION__, __LINE__);
   17.79 +		return NULL;
   17.80 +	}
   17.81  
   17.82  	dom = (struct domain *)malloc(sizeof(struct domain));
   17.83  	if (dom == NULL) {
   17.84 @@ -518,6 +544,8 @@ static struct domain *create_domain(int 
   17.85  	dom->buffer.size = 0;
   17.86  	dom->buffer.capacity = 0;
   17.87  	dom->buffer.max_capacity = 0;
   17.88 +	dom->event_count = 0;
   17.89 +	dom->next_period = (tv.tv_sec * 1000) + (tv.tv_usec / 1000) + RATE_LIMIT_PERIOD;
   17.90  	dom->next = NULL;
   17.91  
   17.92  	dom->ring_ref = -1;
   17.93 @@ -704,14 +732,17 @@ static void handle_tty_write(struct doma
   17.94  
   17.95  static void handle_ring_read(struct domain *dom)
   17.96  {
   17.97 -	evtchn_port_t port;
   17.98 +	evtchn_port_or_error_t port;
   17.99  
  17.100  	if ((port = xc_evtchn_pending(dom->xce_handle)) == -1)
  17.101  		return;
  17.102  
  17.103 +	dom->event_count++;
  17.104 +
  17.105  	buffer_append(dom);
  17.106  
  17.107 -	(void)xc_evtchn_unmask(dom->xce_handle, port);
  17.108 +	if (dom->event_count < RATE_LIMIT_ALLOWANCE)
  17.109 +		(void)xc_evtchn_unmask(dom->xce_handle, port);
  17.110  }
  17.111  
  17.112  static void handle_xs(void)
  17.113 @@ -743,12 +774,20 @@ static void handle_hv_logs(void)
  17.114  	char buffer[1024*16];
  17.115  	char *bufptr = buffer;
  17.116  	unsigned int size = sizeof(buffer);
  17.117 -	if (xc_readconsolering(xc_handle, &bufptr, &size, 1) == 0) {
  17.118 +	static uint32_t index = 0;
  17.119 +	evtchn_port_or_error_t port;
  17.120 +
  17.121 +	if ((port = xc_evtchn_pending(xce_handle)) == -1)
  17.122 +		return;
  17.123 +
  17.124 +	if (xc_readconsolering(xc_handle, &bufptr, &size, 0, 1, &index) == 0) {
  17.125  		int len = write(log_hv_fd, buffer, size);
  17.126  		if (len < 0)
  17.127  			dolog(LOG_ERR, "Failed to write hypervisor log: %d (%s)",
  17.128  			      errno, strerror(errno));
  17.129  	}
  17.130 +
  17.131 +	(void)xc_evtchn_unmask(xce_handle, port);
  17.132  }
  17.133  
  17.134  static void handle_log_reload(void)
  17.135 @@ -776,17 +815,34 @@ void handle_io(void)
  17.136  
  17.137  	if (log_hv) {
  17.138  		xc_handle = xc_interface_open();
  17.139 -		if (xc_handle == -1)
  17.140 +		if (xc_handle == -1) {
  17.141  			dolog(LOG_ERR, "Failed to open xc handle: %d (%s)",
  17.142  			      errno, strerror(errno));
  17.143 -		else
  17.144 -			log_hv_fd = create_hv_log();
  17.145 +			goto out;
  17.146 +		}
  17.147 +		xce_handle = xc_evtchn_open();
  17.148 +		if (xce_handle == -1) {
  17.149 +			dolog(LOG_ERR, "Failed to open xce handle: %d (%s)",
  17.150 +			      errno, strerror(errno));
  17.151 +			goto out;
  17.152 +		}
  17.153 +		log_hv_fd = create_hv_log();
  17.154 +		if (log_hv_fd == -1)
  17.155 +			goto out;
  17.156 +		log_hv_evtchn = xc_evtchn_bind_virq(xce_handle, VIRQ_CON_RING);
  17.157 +		if (log_hv_evtchn == -1) {
  17.158 +			dolog(LOG_ERR, "Failed to bind to VIRQ_CON_RING: "
  17.159 +			      "%d (%s)", errno, strerror(errno));
  17.160 +			goto out;
  17.161 +		}
  17.162  	}
  17.163  
  17.164  	for (;;) {
  17.165  		struct domain *d, *n;
  17.166 -		struct timeval timeout = { 1, 0 }; /* Read HV logs every 1 second */
  17.167  		int max_fd = -1;
  17.168 +		struct timeval timeout;
  17.169 +		struct timeval tv;
  17.170 +		long long now, next_timeout = 0;
  17.171  
  17.172  		FD_ZERO(&readfds);
  17.173  		FD_ZERO(&writefds);
  17.174 @@ -794,8 +850,38 @@ void handle_io(void)
  17.175  		FD_SET(xs_fileno(xs), &readfds);
  17.176  		max_fd = MAX(xs_fileno(xs), max_fd);
  17.177  
  17.178 +		if (log_hv) {
  17.179 +			FD_SET(xc_evtchn_fd(xce_handle), &readfds);
  17.180 +			max_fd = MAX(xc_evtchn_fd(xce_handle), max_fd);
  17.181 +		}
  17.182 +
  17.183 +		if (gettimeofday(&tv, NULL) < 0)
  17.184 +			return;
  17.185 +		now = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
  17.186 +
  17.187 +		/* Re-calculate any event counter allowances & unblock
  17.188 +		   domains with new allowance */
  17.189  		for (d = dom_head; d; d = d->next) {
  17.190 -			if (d->xce_handle != -1) {
  17.191 +			/* Add 5ms of fuzz since select() often returns
  17.192 +			   a couple of ms sooner than requested. Without
  17.193 +			   the fuzz we typically do an extra spin in select()
  17.194 +			   with a 1/2 ms timeout every other iteration */
  17.195 +			if ((now+5) > d->next_period) {
  17.196 +				d->next_period = now + RATE_LIMIT_PERIOD;
  17.197 +				if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
  17.198 +					(void)xc_evtchn_unmask(d->xce_handle, d->local_port);
  17.199 +				}
  17.200 +				d->event_count = 0;
  17.201 +			}
  17.202 +		}
  17.203 +
  17.204 +		for (d = dom_head; d; d = d->next) {
  17.205 +			if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
  17.206 +				/* Determine if we're going to be the next time slice to expire */
  17.207 +				if (!next_timeout ||
  17.208 +				    d->next_period < next_timeout)
  17.209 +					next_timeout = d->next_period;
  17.210 +			} else if (d->xce_handle != -1) {
  17.211  				int evtchn_fd = xc_evtchn_fd(d->xce_handle);
  17.212  				FD_SET(evtchn_fd, &readfds);
  17.213  				max_fd = MAX(evtchn_fd, max_fd);
  17.214 @@ -811,11 +897,19 @@ void handle_io(void)
  17.215  			}
  17.216  		}
  17.217  
  17.218 -		/* XXX I wish we didn't have to busy wait for hypervisor logs
  17.219 -		 * but there's no obvious way to get event channel notifications
  17.220 -		 * for new HV log data as we can with guest */
  17.221 +		/* If any domain has been rate limited, we need to work
  17.222 +		   out what timeout to supply to select */
  17.223 +		if (next_timeout) {
  17.224 +			long long duration = (next_timeout - now);
  17.225 +			if (duration <= 0) /* sanity check */
  17.226 +				duration = 1;
  17.227 +			timeout.tv_sec = duration / 1000;
  17.228 +			timeout.tv_usec = ((duration - (timeout.tv_sec * 1000))
  17.229 +					   * 1000);
  17.230 +		}
  17.231 +
  17.232  		ret = select(max_fd + 1, &readfds, &writefds, 0,
  17.233 -			     log_hv_fd != -1 ? &timeout : NULL);
  17.234 +			     next_timeout ? &timeout : NULL);
  17.235  
  17.236  		if (log_reload) {
  17.237  			handle_log_reload();
  17.238 @@ -832,12 +926,10 @@ void handle_io(void)
  17.239  			break;
  17.240  		}
  17.241  
  17.242 -		/* Always process HV logs even if not a timeout */
  17.243 -		if (log_hv_fd != -1)
  17.244 +		if (log_hv && FD_ISSET(xc_evtchn_fd(xce_handle), &readfds))
  17.245  			handle_hv_logs();
  17.246  
  17.247 -		/* Must not check returned FDSET if it was a timeout */
  17.248 -		if (ret == 0)
  17.249 +		if (ret <= 0)
  17.250  			continue;
  17.251  
  17.252  		if (FD_ISSET(xs_fileno(xs), &readfds))
  17.253 @@ -845,9 +937,11 @@ void handle_io(void)
  17.254  
  17.255  		for (d = dom_head; d; d = n) {
  17.256  			n = d->next;
  17.257 -			if (d->xce_handle != -1 &&
  17.258 -			    FD_ISSET(xc_evtchn_fd(d->xce_handle), &readfds))
  17.259 -				handle_ring_read(d);
  17.260 +			if (d->event_count < RATE_LIMIT_ALLOWANCE) {
  17.261 +				if (d->xce_handle != -1 &&
  17.262 +				    FD_ISSET(xc_evtchn_fd(d->xce_handle), &readfds))
  17.263 +					handle_ring_read(d);
  17.264 +			}
  17.265  
  17.266  			if (d->tty_fd != -1 && FD_ISSET(d->tty_fd, &readfds))
  17.267  				handle_tty_read(d);
  17.268 @@ -860,6 +954,7 @@ void handle_io(void)
  17.269  		}
  17.270  	}
  17.271  
  17.272 + out:
  17.273  	if (log_hv_fd != -1) {
  17.274  		close(log_hv_fd);
  17.275  		log_hv_fd = -1;
  17.276 @@ -868,6 +963,11 @@ void handle_io(void)
  17.277  		xc_interface_close(xc_handle);
  17.278  		xc_handle = -1;
  17.279  	}
  17.280 +	if (xce_handle != -1) {
  17.281 +		xc_evtchn_close(xce_handle);
  17.282 +		xce_handle = -1;
  17.283 +	}
  17.284 +	log_hv_evtchn = -1;
  17.285  }
  17.286  
  17.287  /*
    18.1 --- a/tools/examples/xend-config.sxp	Tue Oct 30 11:33:55 2007 -0600
    18.2 +++ b/tools/examples/xend-config.sxp	Tue Oct 30 15:34:44 2007 -0600
    18.3 @@ -192,8 +192,39 @@
    18.4  # Empty string is no authentication.
    18.5  (vncpasswd '')
    18.6  
    18.7 +# The VNC server can be told to negotiate a TLS session
    18.8 +# to encryption all traffic, and provide x509 cert to
    18.9 +# clients enalbing them to verify server identity. The
   18.10 +# GTK-VNC widget, virt-viewer, virt-manager and VeNCrypt
   18.11 +# all support the VNC extension for TLS used in QEMU. The
   18.12 +# TightVNC/RealVNC/UltraVNC clients do not.
   18.13 +#
   18.14 +# To enable this create x509 certificates / keys in the
   18.15 +# directory /etc/xen/vnc
   18.16 +#
   18.17 +#  ca-cert.pem       - The CA certificate
   18.18 +#  server-cert.pem   - The Server certificate signed by the CA
   18.19 +#  server-key.pem    - The server private key
   18.20 +#
   18.21 +# and then uncomment this next line
   18.22 +# (vnc-tls 1)
   18.23 +
   18.24 +# The certificate dir can be pointed elsewhere..
   18.25 +#
   18.26 +# (vnc-x509-cert-dir /etc/xen/vnc)
   18.27 +
   18.28 +# The server can be told to request & validate an x509
   18.29 +# certificate from the client. Only clients with a cert
   18.30 +# signed by the trusted CA will be able to connect. This
   18.31 +# is more secure the password auth alone. Passwd auth can
   18.32 +# used at the same time if desired. To enable client cert
   18.33 +# checking uncomment this:
   18.34 +#
   18.35 +# (vnc-x509-verify 1)
   18.36 +
   18.37  # The default keymap to use for the VM's virtual keyboard
   18.38  # when not specififed in VM's configuration
   18.39  #(keymap 'en-us')
   18.40  
   18.41 -
   18.42 +# Script to run when the label of a resource has changed.
   18.43 +#(resource-label-change-script '')
    19.1 --- a/tools/firmware/hvmloader/acpi/build.c	Tue Oct 30 11:33:55 2007 -0600
    19.2 +++ b/tools/firmware/hvmloader/acpi/build.c	Tue Oct 30 15:34:44 2007 -0600
    19.3 @@ -226,7 +226,7 @@ static int construct_processor_objects(u
    19.4      }
    19.5  
    19.6      /* NameString */
    19.7 -    strncpy(p, pr_scope, strlen(pr_scope));
    19.8 +    strncpy((char *)p, pr_scope, strlen(pr_scope));
    19.9      p += strlen(pr_scope);
   19.10  
   19.11      /*
    20.1 --- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c	Tue Oct 30 11:33:55 2007 -0600
    20.2 +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c	Tue Oct 30 15:34:44 2007 -0600
    20.3 @@ -591,7 +591,7 @@ void tcpa_add_measurement(uint32_t pcrIn
    20.4  	case EV_SEPARATOR:
    20.5  		tcpa_add_measurement_to_log_simple(pcrIndex,
    20.6  		                            event_type,
    20.7 -		                            evt_separator,
    20.8 +		                            (uint8_t *)evt_separator,
    20.9  		                            4);
   20.10  	break;
   20.11  	case EV_ACTION:
    21.1 --- a/tools/firmware/vgabios/clext.c	Tue Oct 30 11:33:55 2007 -0600
    21.2 +++ b/tools/firmware/vgabios/clext.c	Tue Oct 30 15:34:44 2007 -0600
    21.3 @@ -1489,14 +1489,26 @@ cirrus_clear_vram_1:
    21.4    mov dx, #0x3ce
    21.5    out dx, ax
    21.6    push ax
    21.7 -  mov cx, #0xa000
    21.8 -  mov es, cx
    21.9 -  xor di, di
   21.10 +
   21.11 +;; Windows Vista appears to be emulating this sequence as part of changing 
   21.12 +;; screen resolution, but it generates 4096 writes per iteration.
   21.13 +;; Instead, use a magic register sequence to write the whole bank.
   21.14 +;;mov cx, #0xa000
   21.15 +;;mov es, cx
   21.16 +;;xor di, di
   21.17 +;;mov ax, si
   21.18 +;;mov cx, #8192
   21.19 +;;cld
   21.20 +;;rep
   21.21 +;;    stosw
   21.22    mov ax, si
   21.23 -  mov cx, #8192
   21.24 -  cld
   21.25 -  rep
   21.26 -      stosw
   21.27 +  shl ax, #8
   21.28 +  mov al, #0xfe
   21.29 +  out dx, ax	;; Low byte of value to be written to the bank
   21.30 +  mov ax, si
   21.31 +  mov al, #0xff  
   21.32 +  out dx, ax    ;; High byte and trigger the write
   21.33 +
   21.34    pop ax
   21.35    inc ah
   21.36    cmp ah, bl
    22.1 --- a/tools/firmware/vmxassist/machine.h	Tue Oct 30 11:33:55 2007 -0600
    22.2 +++ b/tools/firmware/vmxassist/machine.h	Tue Oct 30 15:34:44 2007 -0600
    22.3 @@ -38,10 +38,15 @@
    22.4  #define CR4_PSE		(1 << 4)
    22.5  #define CR4_PAE		(1 << 5)
    22.6  
    22.7 +#define EFLAGS_CF	(1 << 0)
    22.8 +#define EFLAGS_PF	(1 << 2)
    22.9 +#define EFLAGS_AF	(1 << 4)
   22.10  #define EFLAGS_ZF	(1 << 6)
   22.11 +#define EFLAGS_SF	(1 << 7)
   22.12  #define EFLAGS_TF	(1 << 8)
   22.13  #define EFLAGS_IF	(1 << 9)
   22.14  #define EFLAGS_DF	(1 << 10)
   22.15 +#define EFLAGS_OF	(1 << 11)
   22.16  #define EFLAGS_IOPL	(3 << 12)
   22.17  #define EFLAGS_VM	((1 << 17) | EFLAGS_IOPL)
   22.18  #define EFLAGS_VIF	(1 << 19)
    23.1 --- a/tools/firmware/vmxassist/vm86.c	Tue Oct 30 11:33:55 2007 -0600
    23.2 +++ b/tools/firmware/vmxassist/vm86.c	Tue Oct 30 15:34:44 2007 -0600
    23.3 @@ -33,6 +33,7 @@
    23.4  #define	SEG_SS		0x0020
    23.5  #define	SEG_FS		0x0040
    23.6  #define	SEG_GS		0x0080
    23.7 +#define REP		0x0100
    23.8  
    23.9  static unsigned prev_eip = 0;
   23.10  enum vm86_mode mode = 0;
   23.11 @@ -656,6 +657,108 @@ movr(struct regs *regs, unsigned prefix,
   23.12  }
   23.13  
   23.14  /*
   23.15 + * We need to handle string moves that address memory beyond the 64KB segment
   23.16 + * limit that VM8086 mode enforces.
   23.17 + */
   23.18 +static inline int
   23.19 +movs(struct regs *regs, unsigned prefix, unsigned opc)
   23.20 +{
   23.21 +	unsigned eip = regs->eip - 1;
   23.22 +	unsigned sseg = segment(prefix, regs, regs->vds);
   23.23 +	unsigned dseg = regs->ves;
   23.24 +	unsigned saddr, daddr;
   23.25 +	unsigned count = 1;
   23.26 +	int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
   23.27 +
   23.28 +	saddr = address(regs, sseg, regs->esi);
   23.29 +	daddr = address(regs, dseg, regs->edi);
   23.30 +
   23.31 +	if ((prefix & REP) != 0) {
   23.32 +		count = regs->ecx;
   23.33 +		regs->ecx = 0;
   23.34 +	}
   23.35 +
   23.36 +	switch (opc) {
   23.37 +	case 0xA4: /* movsb */
   23.38 +		regs->esi += (incr * count);
   23.39 +		regs->edi += (incr * count);
   23.40 +
   23.41 +		while (count-- != 0) {
   23.42 +			write8(daddr, read8(saddr));
   23.43 +			daddr += incr;
   23.44 +			saddr += incr;
   23.45 +		}
   23.46 +		TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)"));
   23.47 +		break;
   23.48 +
   23.49 +	case 0xA5: /* movsw */
   23.50 +		if ((prefix & DATA32) == 0) {
   23.51 +			incr = 2 * incr;
   23.52 +			regs->esi += (incr * count);
   23.53 +			regs->edi += (incr * count);
   23.54 +
   23.55 +			while (count-- != 0) {
   23.56 +				write16(daddr, read16(saddr));
   23.57 +				daddr += incr;
   23.58 +				saddr += incr;
   23.59 +			}
   23.60 +		} else {
   23.61 +			incr = 4 * incr;
   23.62 +			regs->esi += (incr * count);
   23.63 +			regs->edi += (incr * count);
   23.64 +
   23.65 +			while (count-- != 0) {
   23.66 +				write32(daddr, read32(saddr));
   23.67 +				daddr += incr;
   23.68 +				saddr += incr;
   23.69 +			}
   23.70 +		}			
   23.71 +		TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)"));
   23.72 +		break;
   23.73 +	}
   23.74 +
   23.75 +	return 1;
   23.76 +}
   23.77 +
   23.78 +static inline int
   23.79 +lods(struct regs *regs, unsigned prefix, unsigned opc)
   23.80 +{
   23.81 +	unsigned eip = regs->eip - 1;
   23.82 +	unsigned seg = segment(prefix, regs, regs->vds);
   23.83 +	unsigned addr = address(regs, seg, regs->esi);
   23.84 +	unsigned count = 1;
   23.85 +	int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
   23.86 +
   23.87 +	if ((prefix & REP) != 0) {
   23.88 +		count = regs->ecx;
   23.89 +		regs->ecx = 0;
   23.90 +	}
   23.91 +
   23.92 +	switch (opc) {
   23.93 +	case 0xAD: /* lodsw */
   23.94 +		if ((prefix & DATA32) == 0) {
   23.95 +			incr = 2 * incr;
   23.96 +			regs->esi += (incr * count);
   23.97 +			while (count-- != 0) {
   23.98 +				setreg16(regs, 0, read16(addr));
   23.99 +				addr += incr;
  23.100 +			}
  23.101 +
  23.102 +			TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax"));
  23.103 +		} else {
  23.104 +			incr = 4 * incr;
  23.105 +			regs->esi += (incr * count);
  23.106 +			while (count-- != 0) {
  23.107 +				setreg32(regs, 0, read32(addr));
  23.108 +				addr += incr;
  23.109 +			}
  23.110 +			TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax"));
  23.111 +		}
  23.112 +		break;
  23.113 +	}
  23.114 +	return 1;
  23.115 +}
  23.116 +/*
  23.117   * Move to and from a control register.
  23.118   */
  23.119  static int
  23.120 @@ -718,6 +821,55 @@ static inline void set_eflags_ZF(unsigne
  23.121  		regs->eflags &= ~EFLAGS_ZF;
  23.122  }
  23.123  
  23.124 +static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2,
  23.125 +				unsigned result, struct regs *regs)
  23.126 +{
  23.127 +	int bit_count;
  23.128 +	unsigned tmp;
  23.129 +	unsigned full_mask;
  23.130 +	unsigned nonsign_mask;
  23.131 +
  23.132 +	/* Carry out of high order bit? */
  23.133 +	if ( v1 & v2 & hi_bit_mask )
  23.134 +		regs->eflags |= EFLAGS_CF;
  23.135 +	else
  23.136 +		regs->eflags &= ~EFLAGS_CF;
  23.137 +
  23.138 +	/* Even parity in least significant byte? */
  23.139 +	tmp = result & 0xff;
  23.140 +	for (bit_count = 0; tmp != 0; bit_count++)
  23.141 +		tmp &= (tmp - 1);
  23.142 +
  23.143 +	if (bit_count & 1)
  23.144 +		regs->eflags &= ~EFLAGS_PF;
  23.145 +	else
  23.146 +		regs->eflags |= EFLAGS_PF;
  23.147 +
  23.148 +	/* Carry out of least significant BCD digit? */
  23.149 +	if ( v1 & v2 & (1<<3) )
  23.150 +		regs->eflags |= EFLAGS_AF;
  23.151 +	else
  23.152 +		regs->eflags &= ~EFLAGS_AF;
  23.153 +
  23.154 +	/* Result is zero? */
  23.155 +	full_mask = (hi_bit_mask - 1) | hi_bit_mask;
  23.156 +	set_eflags_ZF(full_mask, result, regs);
  23.157 +
  23.158 +	/* Sign of result? */
  23.159 +	if ( result & hi_bit_mask )
  23.160 +		regs->eflags |= EFLAGS_SF;
  23.161 +	else
  23.162 +		regs->eflags &= ~EFLAGS_SF;
  23.163 +
  23.164 +	/* Carry out of highest non-sign bit? */
  23.165 +	nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask;
  23.166 +	if ( v1 & v2 & hi_bit_mask )
  23.167 +		regs->eflags |= EFLAGS_OF;
  23.168 +	else
  23.169 +		regs->eflags &= ~EFLAGS_OF;
  23.170 +
  23.171 +}
  23.172 +
  23.173  /*
  23.174   * We need to handle cmp opcodes that address memory beyond the 64KB
  23.175   * segment limit that VM8086 mode enforces.
  23.176 @@ -792,6 +944,82 @@ test(struct regs *regs, unsigned prefix,
  23.177  }
  23.178  
  23.179  /*
  23.180 + * We need to handle add opcodes that address memory beyond the 64KB
  23.181 + * segment limit that VM8086 mode enforces.
  23.182 + */
  23.183 +static int
  23.184 +add(struct regs *regs, unsigned prefix, unsigned opc)
  23.185 +{
  23.186 +	unsigned eip = regs->eip - 1;
  23.187 +	unsigned modrm = fetch8(regs);
  23.188 +	unsigned addr = operand(prefix, regs, modrm);
  23.189 +	unsigned r = (modrm >> 3) & 7;
  23.190 +
  23.191 +	unsigned val1 = 0;
  23.192 +	unsigned val2 = 0;
  23.193 +	unsigned result = 0;
  23.194 +	unsigned hi_bit;
  23.195 +
  23.196 +	if ((modrm & 0xC0) == 0xC0) /* no registers */
  23.197 +		return 0;
  23.198 +
  23.199 +	switch (opc) {
  23.200 +	case 0x00: /* addr32 add r8, r/m8 */
  23.201 +		val1 = getreg8(regs, r);
  23.202 +		val2 = read8(addr);
  23.203 +		result = val1 + val2;
  23.204 +		write8(addr, result);
  23.205 +		TRACE((regs, regs->eip - eip,
  23.206 +			"addb %%e%s, *0x%x", rnames[r], addr));
  23.207 +		break;
  23.208 +		
  23.209 +	case 0x01: /* addr32 add r16, r/m16 */
  23.210 +		if (prefix & DATA32) {
  23.211 +			val1 = getreg32(regs, r);
  23.212 +			val2 = read32(addr);
  23.213 +			result = val1 + val2;
  23.214 +			write32(addr, result);
  23.215 +			TRACE((regs, regs->eip - eip,
  23.216 +				"addl %%e%s, *0x%x", rnames[r], addr));
  23.217 +		} else {
  23.218 +			val1 = getreg16(regs, r);
  23.219 +			val2 = read16(addr);
  23.220 +			result = val1 + val2;
  23.221 +			write16(addr, result);
  23.222 +			TRACE((regs, regs->eip - eip,
  23.223 +				"addw %%e%s, *0x%x", rnames[r], addr));
  23.224 +		}
  23.225 +		break;
  23.226 +		
  23.227 +	case 0x03: /* addr32 add r/m16, r16 */
  23.228 +		if (prefix & DATA32) {
  23.229 +			val1 = getreg32(regs, r);
  23.230 +			val2 = read32(addr);
  23.231 +			result = val1 + val2;
  23.232 +			setreg32(regs, r, result);
  23.233 +			TRACE((regs, regs->eip - eip,
  23.234 +				"addl *0x%x, %%e%s", addr, rnames[r]));
  23.235 +		} else {
  23.236 +			val1 = getreg16(regs, r);
  23.237 +			val2 = read16(addr);
  23.238 +			result = val1 + val2;
  23.239 +			setreg16(regs, r, result);
  23.240 +			TRACE((regs, regs->eip - eip,
  23.241 +				"addw *0x%x, %%%s", addr, rnames[r]));
  23.242 +		}
  23.243 +		break;
  23.244 +	}
  23.245 +
  23.246 +	if (opc == 0x00)
  23.247 +		hi_bit = (1<<7);
  23.248 +	else
  23.249 +		hi_bit = (prefix & DATA32) ? (1<<31) : (1<<15);
  23.250 +	set_eflags_add(hi_bit, val1, val2, result, regs);
  23.251 +
  23.252 +	return 1;
  23.253 +}
  23.254 +
  23.255 +/*
  23.256   * We need to handle pop opcodes that address memory beyond the 64KB
  23.257   * segment limit that VM8086 mode enforces.
  23.258   */
  23.259 @@ -1314,6 +1542,18 @@ opcode(struct regs *regs)
  23.260  
  23.261  	for (;;) {
  23.262  		switch ((opc = fetch8(regs))) {
  23.263 +
  23.264 +		case 0x00: /* addr32 add r8, r/m8 */
  23.265 +		case 0x01: /* addr32 add r16, r/m16 */
  23.266 +		case 0x03: /* addr32 add r/m16, r16 */
  23.267 +			if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
  23.268 +				goto invalid;
  23.269 +			if ((prefix & ADDR32) == 0)
  23.270 +				goto invalid;
  23.271 +			if (!add(regs, prefix, opc))
  23.272 +				goto invalid;
  23.273 +			return OPC_EMULATED;
  23.274 +			
  23.275  		case 0x07: /* pop %es */
  23.276  			regs->ves = (prefix & DATA32) ?
  23.277  				pop32(regs) : pop16(regs);
  23.278 @@ -1510,6 +1750,21 @@ opcode(struct regs *regs)
  23.279  			return OPC_EMULATED;
  23.280  		}
  23.281  
  23.282 +		case 0xA4: /* movsb */
  23.283 +		case 0xA5: /* movsw */
  23.284 +			if ((prefix & ADDR32) == 0)
  23.285 +				goto invalid;
  23.286 +			if (!movs(regs, prefix, opc))
  23.287 +				goto invalid;
  23.288 +			return OPC_EMULATED;
  23.289 +
  23.290 +		case 0xAD: /* lodsw */
  23.291 +			if ((prefix & ADDR32) == 0)
  23.292 +				goto invalid;
  23.293 +			if (!lods(regs, prefix, opc))
  23.294 +				goto invalid;
  23.295 +			return OPC_EMULATED;
  23.296 +			
  23.297  		case 0xBB: /* mov bx, imm16 */
  23.298  		{
  23.299  			int data;
  23.300 @@ -1627,6 +1882,11 @@ opcode(struct regs *regs)
  23.301  			/* Do something power-saving here! */
  23.302  			return OPC_EMULATED;
  23.303  
  23.304 +		case 0xF3: /* rep/repe/repz */
  23.305 +			TRACE((regs, regs->eip - eip, "rep"));
  23.306 +			prefix |= REP;
  23.307 +			continue;
  23.308 +
  23.309  		case 0xF6: /* addr32 testb $imm, r/m8 */
  23.310  			if (!(prefix & ADDR32))
  23.311  				goto invalid;
  23.312 @@ -1660,6 +1920,7 @@ emulate(struct regs *regs)
  23.313  {
  23.314  	unsigned flteip;
  23.315  	int nemul = 0;
  23.316 +	unsigned ip;
  23.317  
  23.318  	/* emulate as many instructions as possible */
  23.319  	while (opcode(regs) != OPC_INVALID)
  23.320 @@ -1668,6 +1929,12 @@ emulate(struct regs *regs)
  23.321  	/* detect the case where we are not making progress */
  23.322  	if (nemul == 0 && prev_eip == regs->eip) {
  23.323  		flteip = address(regs, MASK16(regs->cs), regs->eip);
  23.324 +
  23.325 +		printf("Undecoded sequence: \n");
  23.326 +		for (ip=flteip; ip < flteip+16; ip++)
  23.327 +			printf("0x%02x ", read8(ip));
  23.328 +		printf("\n");
  23.329 +
  23.330  		panic("Unknown opcode at %04x:%04x=0x%x",
  23.331  			MASK16(regs->cs), regs->eip, flteip);
  23.332  	} else
    24.1 --- a/tools/ioemu/Makefile.target	Tue Oct 30 11:33:55 2007 -0600
    24.2 +++ b/tools/ioemu/Makefile.target	Tue Oct 30 15:34:44 2007 -0600
    24.3 @@ -387,6 +387,11 @@ SOUND_HW += fmopl.o adlib.o
    24.4  endif
    24.5  AUDIODRV+= wavcapture.o
    24.6  
    24.7 +ifdef CONFIG_VNC_TLS
    24.8 +CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
    24.9 +LIBS += $(CONFIG_VNC_TLS_LIBS)
   24.10 +endif
   24.11 +
   24.12  # SCSI layer
   24.13  VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
   24.14  
   24.15 @@ -409,6 +414,10 @@ VL_OBJS+= usb-uhci.o smbus_eeprom.o
   24.16  VL_OBJS+= piix4acpi.o
   24.17  VL_OBJS+= xenstore.o
   24.18  VL_OBJS+= xen_platform.o
   24.19 +VL_OBJS+= xen_machine_fv.o
   24.20 +VL_OBJS+= xen_machine_pv.o
   24.21 +VL_OBJS+= xenfb.o
   24.22 +VL_OBJS+= xen_console.o
   24.23  VL_OBJS+= tpm_tis.o
   24.24  CPPFLAGS += -DHAS_AUDIO
   24.25  endif
   24.26 @@ -452,8 +461,7 @@ endif
   24.27  ifdef CONFIG_SDL
   24.28  VL_OBJS+=sdl.o x_keymap.o
   24.29  endif
   24.30 -VL_OBJS+=vnc.o
   24.31 -VL_OBJS+=d3des.o
   24.32 +VL_OBJS+=vnc.o d3des.o
   24.33  ifdef CONFIG_COCOA
   24.34  VL_OBJS+=cocoa.o
   24.35  COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
   24.36 @@ -511,12 +519,9 @@ cocoa.o: cocoa.m
   24.37  sdl.o: sdl.c keymaps.c sdl_keysym.h
   24.38  	$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
   24.39  
   24.40 -vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
   24.41 +vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
   24.42  	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
   24.43  
   24.44 -d3des.o: d3des.c d3des.h
   24.45 -	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
   24.46 -
   24.47  sdlaudio.o: sdlaudio.c
   24.48  	$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
   24.49  
    25.1 --- a/tools/ioemu/configure	Tue Oct 30 11:33:55 2007 -0600
    25.2 +++ b/tools/ioemu/configure	Tue Oct 30 15:34:44 2007 -0600
    25.3 @@ -87,6 +87,7 @@ alsa="no"
    25.4  fmod="no"
    25.5  fmod_lib=""
    25.6  fmod_inc=""
    25.7 +vnc_tls="yes"
    25.8  bsd="no"
    25.9  linux="no"
   25.10  kqemu="no"
   25.11 @@ -225,6 +226,8 @@ for opt do
   25.12    ;;
   25.13    --fmod-inc=*) fmod_inc="$optarg"
   25.14    ;;
   25.15 +  --disable-vnc-tls) vnc_tls="no"
   25.16 +  ;;
   25.17    --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
   25.18    ;;
   25.19    --disable-slirp) slirp="no"
   25.20 @@ -292,6 +295,7 @@ echo "  --enable-coreaudio       enable 
   25.21  echo "  --enable-alsa            enable ALSA audio driver"
   25.22  echo "  --enable-fmod            enable FMOD audio driver"
   25.23  echo "  --enabled-dsound         enable DirectSound audio driver"
   25.24 +echo "  --disable-vnc-tls        disable TLS encryption for VNC server"
   25.25  echo "  --enable-system          enable all system emulation targets"
   25.26  echo "  --disable-system         disable all system emulation targets"
   25.27  echo "  --enable-linux-user      enable all linux usermode emulation targets"
   25.28 @@ -410,6 +414,18 @@ if test "$solaris" = "yes" ; then
   25.29    fi
   25.30  fi 
   25.31  
   25.32 +##########################################
   25.33 +
   25.34 +# VNC TLS detection
   25.35 +if test "$vnc_tls" = "yes" ; then
   25.36 +  `pkg-config gnutls` || vnc_tls="no"
   25.37 +fi
   25.38 +if test "$vnc_tls" = "yes" ; then
   25.39 +  vnc_tls_cflags=`pkg-config --cflags gnutls`
   25.40 +  vnc_tls_libs=`pkg-config --libs gnutls`
   25.41 +fi
   25.42 +
   25.43 +##########################################
   25.44  
   25.45  if test -z "$target_list" ; then
   25.46  # these targets are portable
   25.47 @@ -772,6 +788,12 @@ if test "$fmod" = "yes" ; then
   25.48    echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
   25.49    echo "#define CONFIG_FMOD 1" >> $config_h
   25.50  fi
   25.51 +if test "$vnc_tls" = "yes" ; then
   25.52 +  echo "CONFIG_VNC_TLS=yes" >> $config_mak
   25.53 +  echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_mak
   25.54 +  echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak
   25.55 +  echo "#define CONFIG_VNC_TLS 1" >> $config_h
   25.56 +fi
   25.57  qemu_version=`head $source_path/VERSION`
   25.58  echo "VERSION=$qemu_version" >>$config_mak
   25.59  echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
   25.60 @@ -999,4 +1021,10 @@ if test "$source_path_used" = "yes" ; th
   25.61      done
   25.62  fi
   25.63  
   25.64 +echo "VNC TLS support   $vnc_tls"
   25.65 +if test "$vnc_tls" = "yes" ; then
   25.66 +    echo "    TLS CFLAGS    $vnc_tls_cflags"
   25.67 +    echo "    TLS LIBS      $vnc_tls_libs"
   25.68 +fi
   25.69 +
   25.70  rm -f $TMPO $TMPC $TMPE $TMPS
    26.1 --- a/tools/ioemu/hw/cirrus_vga.c	Tue Oct 30 11:33:55 2007 -0600
    26.2 +++ b/tools/ioemu/hw/cirrus_vga.c	Tue Oct 30 15:34:44 2007 -0600
    26.3 @@ -294,6 +294,7 @@ void *shared_vram;
    26.4  
    26.5  static void cirrus_bitblt_reset(CirrusVGAState *s);
    26.6  static void cirrus_update_memory_access(CirrusVGAState *s);
    26.7 +static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val);
    26.8  
    26.9  /***************************************
   26.10   *
   26.11 @@ -1497,6 +1498,17 @@ cirrus_hook_write_gr(CirrusVGAState * s,
   26.12      case 0x31:			// BLT STATUS/START
   26.13  	cirrus_write_bitblt(s, reg_value);
   26.14  	break;
   26.15 +
   26.16 +	// Extension to allow BIOS to clear 16K VRAM bank in one operation
   26.17 +    case 0xFE:
   26.18 +	s->gr[reg_index] = reg_value;  // Lower byte of value to be written
   26.19 +	break;
   26.20 +    case 0xFF: {
   26.21 +	target_phys_addr_t addr;
   26.22 +	for (addr = 0xa0000; addr < 0xa4000; addr += 2)
   26.23 +	    cirrus_vga_mem_writew(s, addr, (reg_value << 8) | s->gr[0xFE]);
   26.24 +	}
   26.25 +	break;
   26.26      default:
   26.27  #ifdef DEBUG_CIRRUS
   26.28  	printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/ioemu/hw/xen_console.c	Tue Oct 30 15:34:44 2007 -0600
    27.3 @@ -0,0 +1,432 @@
    27.4 +/*
    27.5 + *  Copyright (C) International Business Machines  Corp., 2005
    27.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
    27.7 + *
    27.8 + *  Copyright (C) Red Hat 2007
    27.9 + *
   27.10 + *  Xen Console
   27.11 + *
   27.12 + *  This program is free software; you can redistribute it and/or modify
   27.13 + *  it under the terms of the GNU General Public License as published by
   27.14 + *  the Free Software Foundation; under version 2 of the License.
   27.15 + * 
   27.16 + *  This program is distributed in the hope that it will be useful,
   27.17 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.18 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.19 + *  GNU General Public License for more details.
   27.20 + * 
   27.21 + *  You should have received a copy of the GNU General Public License
   27.22 + *  along with this program; if not, write to the Free Software
   27.23 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27.24 + */
   27.25 +
   27.26 +#include <malloc.h>
   27.27 +#include <stdlib.h>
   27.28 +#include <errno.h>
   27.29 +#include <string.h>
   27.30 +#include <sys/select.h>
   27.31 +#include <fcntl.h>
   27.32 +#include <unistd.h>
   27.33 +#include <termios.h>
   27.34 +#include <stdarg.h>
   27.35 +#include <sys/mman.h>
   27.36 +#include <xs.h>
   27.37 +#include <xen/io/console.h>
   27.38 +#include <xenctrl.h>
   27.39 +
   27.40 +#include "vl.h"
   27.41 +
   27.42 +#include "xen_console.h"
   27.43 +
   27.44 +#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
   27.45 +
   27.46 +struct buffer
   27.47 +{
   27.48 +	uint8_t *data;
   27.49 +	size_t consumed;
   27.50 +	size_t size;
   27.51 +	size_t capacity;
   27.52 +	size_t max_capacity;
   27.53 +};
   27.54 +
   27.55 +struct domain
   27.56 +{
   27.57 +	int domid;
   27.58 +	struct buffer buffer;
   27.59 +
   27.60 +	char *conspath;
   27.61 +	char *serialpath;
   27.62 +	int use_consolepath;
   27.63 +	int ring_ref;
   27.64 +	evtchn_port_t local_port;
   27.65 +	evtchn_port_t remote_port;
   27.66 +	int xce_handle;
   27.67 +	struct xs_handle *xsh;
   27.68 +	struct xencons_interface *interface;
   27.69 +	CharDriverState *chr;
   27.70 +};
   27.71 +
   27.72 +
   27.73 +static void buffer_append(struct domain *dom)
   27.74 +{
   27.75 +	struct buffer *buffer = &dom->buffer;
   27.76 +	XENCONS_RING_IDX cons, prod, size;
   27.77 +	struct xencons_interface *intf = dom->interface;
   27.78 +
   27.79 +	cons = intf->out_cons;
   27.80 +	prod = intf->out_prod;
   27.81 +	mb();
   27.82 +
   27.83 +	size = prod - cons;
   27.84 +	if ((size == 0) || (size > sizeof(intf->out)))
   27.85 +		return;
   27.86 +
   27.87 +	if ((buffer->capacity - buffer->size) < size) {
   27.88 +		buffer->capacity += (size + 1024);
   27.89 +		buffer->data = realloc(buffer->data, buffer->capacity);
   27.90 +		if (buffer->data == NULL) {
   27.91 +			dolog(LOG_ERR, "Memory allocation failed");
   27.92 +			exit(ENOMEM);
   27.93 +		}
   27.94 +	}
   27.95 +
   27.96 +	while (cons != prod)
   27.97 +		buffer->data[buffer->size++] = intf->out[
   27.98 +			MASK_XENCONS_IDX(cons++, intf->out)];
   27.99 +
  27.100 +	mb();
  27.101 +	intf->out_cons = cons;
  27.102 +	xc_evtchn_notify(dom->xce_handle, dom->local_port);
  27.103 +
  27.104 +	if (buffer->max_capacity &&
  27.105 +	    buffer->size > buffer->max_capacity) {
  27.106 +		/* Discard the middle of the data. */
  27.107 +
  27.108 +		size_t over = buffer->size - buffer->max_capacity;
  27.109 +		uint8_t *maxpos = buffer->data + buffer->max_capacity;
  27.110 +
  27.111 +		memmove(maxpos - over, maxpos, over);
  27.112 +		buffer->data = realloc(buffer->data, buffer->max_capacity);
  27.113 +		buffer->size = buffer->capacity = buffer->max_capacity;
  27.114 +
  27.115 +		if (buffer->consumed > buffer->max_capacity - over)
  27.116 +			buffer->consumed = buffer->max_capacity - over;
  27.117 +	}
  27.118 +}
  27.119 +
  27.120 +static void buffer_advance(struct buffer *buffer, size_t len)
  27.121 +{
  27.122 +	buffer->consumed += len;
  27.123 +	if (buffer->consumed == buffer->size) {
  27.124 +		buffer->consumed = 0;
  27.125 +		buffer->size = 0;
  27.126 +	}
  27.127 +}
  27.128 +
  27.129 +/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
  27.130 +int xs_gather(struct xs_handle *xs, const char *dir, ...)
  27.131 +{
  27.132 +	va_list ap;
  27.133 +	const char *name;
  27.134 +	char *path;
  27.135 +	int ret = 0;
  27.136 +
  27.137 +	va_start(ap, dir);
  27.138 +	while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
  27.139 +		const char *fmt = va_arg(ap, char *);
  27.140 +		void *result = va_arg(ap, void *);
  27.141 +		char *p;
  27.142 +
  27.143 +		if (asprintf(&path, "%s/%s", dir, name) == -1) {
  27.144 +			ret = ENOMEM;
  27.145 +			break;
  27.146 +		}
  27.147 +		p = xs_read(xs, XBT_NULL, path, NULL);
  27.148 +		free(path);
  27.149 +		if (p == NULL) {
  27.150 +			ret = ENOENT;
  27.151 +			break;
  27.152 +		}
  27.153 +		if (fmt) {
  27.154 +			if (sscanf(p, fmt, result) == 0)
  27.155 +				ret = EINVAL;
  27.156 +			free(p);
  27.157 +		} else
  27.158 +			*(char **)result = p;
  27.159 +	}
  27.160 +	va_end(ap);
  27.161 +	return ret;
  27.162 +}
  27.163 +
  27.164 +static int domain_create_ring(struct domain *dom)
  27.165 +{
  27.166 +	int err, remote_port, ring_ref, rc;
  27.167 +
  27.168 +	err = xs_gather(dom->xsh, dom->serialpath,
  27.169 +			"ring-ref", "%u", &ring_ref,
  27.170 +			"port", "%i", &remote_port,
  27.171 +			NULL);
  27.172 +	if (err) {
  27.173 +		err = xs_gather(dom->xsh, dom->conspath,
  27.174 +				"ring-ref", "%u", &ring_ref,
  27.175 +				"port", "%i", &remote_port,
  27.176 +				NULL);
  27.177 +		if (err) {
  27.178 +			fprintf(stderr, "Console: failed to find ring-ref/port yet\n");
  27.179 +			goto out;
  27.180 +		}
  27.181 +		dom->use_consolepath = 1;
  27.182 +	} else
  27.183 +		dom->use_consolepath = 0;
  27.184 +	fprintf(stderr, "Console: got ring-ref %d port %d\n", ring_ref, remote_port);
  27.185 +
  27.186 +	if ((ring_ref == dom->ring_ref) && (remote_port == dom->remote_port))
  27.187 +		goto out;
  27.188 +
  27.189 +	if (ring_ref != dom->ring_ref) {
  27.190 +		if (dom->interface != NULL)
  27.191 +			munmap(dom->interface, getpagesize());
  27.192 +		dom->interface = xc_map_foreign_range(
  27.193 +			xc_handle, dom->domid, getpagesize(),
  27.194 +			PROT_READ|PROT_WRITE,
  27.195 +			(unsigned long)ring_ref);
  27.196 +		if (dom->interface == NULL) {
  27.197 +			err = errno;
  27.198 +			goto out;
  27.199 +		}
  27.200 +		dom->ring_ref = ring_ref;
  27.201 +	}
  27.202 +
  27.203 +	dom->local_port = -1;
  27.204 +	dom->remote_port = -1;
  27.205 +
  27.206 +	dom->xce_handle = xc_evtchn_open();
  27.207 +	if (dom->xce_handle == -1) {
  27.208 +		err = errno;
  27.209 +		goto out;
  27.210 +	}
  27.211 +
  27.212 +	rc = xc_evtchn_bind_interdomain(dom->xce_handle,
  27.213 +		dom->domid, remote_port);
  27.214 +
  27.215 +	if (rc == -1) {
  27.216 +		err = errno;
  27.217 +		xc_evtchn_close(dom->xce_handle);
  27.218 +		dom->xce_handle = -1;
  27.219 +		goto out;
  27.220 +	}
  27.221 +	dom->local_port = rc;
  27.222 +	dom->remote_port = remote_port;
  27.223 +
  27.224 + out:
  27.225 +	return err;
  27.226 +}
  27.227 +
  27.228 +
  27.229 +static struct domain *create_domain(int domid, CharDriverState *chr)
  27.230 +{
  27.231 +	struct domain *dom;
  27.232 +	char *s;
  27.233 +
  27.234 +	dom = (struct domain *)malloc(sizeof(struct domain));
  27.235 +	if (dom == NULL) {
  27.236 +		dolog(LOG_ERR, "Out of memory %s:%s():L%d",
  27.237 +		      __FILE__, __FUNCTION__, __LINE__);
  27.238 +		exit(ENOMEM);
  27.239 +	}
  27.240 +
  27.241 +	dom->domid = domid;
  27.242 +	dom->chr = chr;
  27.243 +
  27.244 +	dom->xsh = xs_daemon_open();
  27.245 +	if (dom->xsh == NULL) {
  27.246 +		fprintf(logfile, "Could not contact xenstore for console watch\n");
  27.247 +		goto out;
  27.248 +	}
  27.249 +
  27.250 +	dom->serialpath = xs_get_domain_path(dom->xsh, dom->domid);
  27.251 +	s = realloc(dom->serialpath, strlen(dom->serialpath) +
  27.252 +		    strlen("/serial/0") + 1);
  27.253 +	if (s == NULL)
  27.254 +		goto out;
  27.255 +	dom->serialpath = s;
  27.256 +	strcat(dom->serialpath, "/serial/0");
  27.257 +
  27.258 +	dom->conspath = xs_get_domain_path(dom->xsh, dom->domid);
  27.259 +	s = realloc(dom->conspath, strlen(dom->conspath) +
  27.260 +		    strlen("/console") + 1);
  27.261 +	if (s == NULL)
  27.262 +		goto out;
  27.263 +	dom->conspath = s;
  27.264 +	strcat(dom->conspath, "/console");
  27.265 +
  27.266 +	dom->buffer.data = 0;
  27.267 +	dom->buffer.consumed = 0;
  27.268 +	dom->buffer.size = 0;
  27.269 +	dom->buffer.capacity = 0;
  27.270 +	dom->buffer.max_capacity = 0;
  27.271 +
  27.272 +	dom->ring_ref = -1;
  27.273 +	dom->local_port = -1;
  27.274 +	dom->remote_port = -1;
  27.275 +	dom->interface = NULL;
  27.276 +	dom->xce_handle = -1;
  27.277 +
  27.278 +
  27.279 +	return dom;
  27.280 + out:
  27.281 +	free(dom->serialpath);
  27.282 +	free(dom->conspath);
  27.283 +	free(dom);
  27.284 +	return NULL;
  27.285 +}
  27.286 +
  27.287 +
  27.288 +static int ring_free_bytes(struct domain *dom)
  27.289 +{
  27.290 +	struct xencons_interface *intf = dom->interface;
  27.291 +	XENCONS_RING_IDX cons, prod, space;
  27.292 +
  27.293 +	cons = intf->in_cons;
  27.294 +	prod = intf->in_prod;
  27.295 +	mb();
  27.296 +
  27.297 +	space = prod - cons;
  27.298 +	if (space > sizeof(intf->in))
  27.299 +		return 0; /* ring is screwed: ignore it */
  27.300 +
  27.301 +	return (sizeof(intf->in) - space);
  27.302 +}
  27.303 +
  27.304 +static int xencons_can_receive(void *opaque)
  27.305 +{
  27.306 +	struct domain *dom = (struct domain *)opaque;
  27.307 +
  27.308 +	return ring_free_bytes(dom);
  27.309 +}
  27.310 +
  27.311 +static void xencons_receive(void *opaque, const uint8_t *buf, int len)
  27.312 +{
  27.313 +	struct domain *dom = (struct domain *)opaque;
  27.314 +	int i, max;
  27.315 +	struct xencons_interface *intf = dom->interface;
  27.316 +	XENCONS_RING_IDX prod;
  27.317 +
  27.318 +	max = ring_free_bytes(dom);
  27.319 +	/* The can_receive() func limits this, but check again anyway */
  27.320 +	if (max < len)
  27.321 +		len = max;
  27.322 +
  27.323 +	prod = intf->in_prod;
  27.324 +	for (i = 0; i < len; i++) {
  27.325 +		intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
  27.326 +			buf[i];
  27.327 +	}
  27.328 +	wmb();
  27.329 +	intf->in_prod = prod;
  27.330 +	xc_evtchn_notify(dom->xce_handle, dom->local_port);
  27.331 +}
  27.332 +
  27.333 +static void xencons_send(struct domain *dom)
  27.334 +{
  27.335 +	ssize_t len;
  27.336 +	len = qemu_chr_write(dom->chr, dom->buffer.data + dom->buffer.consumed,
  27.337 +			     dom->buffer.size - dom->buffer.consumed);
  27.338 + 	if (len < 1) {
  27.339 +		/*
  27.340 +		 * Disable log because if we're redirecting to /dev/pts/N we
  27.341 +		 * don't want to flood logs when no client has the PTY open
  27.342 +		 */
  27.343 +		/*
  27.344 +		dolog(LOG_DEBUG, "Write failed on domain %d: %zd, %d\n",
  27.345 +		      dom->domid, len, errno);
  27.346 +		*/
  27.347 +	} else {
  27.348 +		buffer_advance(&dom->buffer, len);
  27.349 +	}
  27.350 +}
  27.351 +
  27.352 +static void xencons_ring_read(void *opaque)
  27.353 +{
  27.354 +	evtchn_port_t port;
  27.355 +	struct domain *dom = (struct domain *)opaque;
  27.356 +
  27.357 +	if ((port = xc_evtchn_pending(dom->xce_handle)) == -1)
  27.358 +		return;
  27.359 +
  27.360 +	buffer_append(dom);
  27.361 +
  27.362 +	(void)xc_evtchn_unmask(dom->xce_handle, port);
  27.363 +
  27.364 +	if (dom->buffer.size - dom->buffer.consumed)
  27.365 +		xencons_send(dom);
  27.366 +}
  27.367 +
  27.368 +static void xencons_startup(void *opaque)
  27.369 +{
  27.370 +	struct domain *dom = (struct domain *)opaque;
  27.371 +	unsigned dummy;
  27.372 +	char **vec;
  27.373 +	int err;
  27.374 +	vec = xs_read_watch(dom->xsh, &dummy);
  27.375 +	if (vec)
  27.376 +		free(vec);
  27.377 +	fprintf(stderr, "Console: got watch\n");
  27.378 +	err = domain_create_ring(dom);
  27.379 +	if (err)
  27.380 +		return;
  27.381 +
  27.382 +	xs_unwatch(dom->xsh, dom->conspath, "");
  27.383 +	xs_unwatch(dom->xsh, dom->serialpath, "");
  27.384 +	qemu_set_fd_handler2(xs_fileno(dom->xsh), NULL, NULL, NULL, NULL);
  27.385 +
  27.386 +	fprintf(stderr, "Console: connected to guest frontend\n");
  27.387 +	if (qemu_set_fd_handler2(dom->xce_handle, NULL, xencons_ring_read, NULL, dom) < 0)
  27.388 +		return;
  27.389 +
  27.390 +	qemu_chr_add_handlers(dom->chr, xencons_can_receive, xencons_receive,
  27.391 +			      NULL, dom);
  27.392 +}
  27.393 +
  27.394 +
  27.395 +int xencons_init(int domid, CharDriverState *chr)
  27.396 +{
  27.397 +	struct domain *dom = create_domain(domid, chr);
  27.398 +
  27.399 +	if (!dom)
  27.400 +		return -1;
  27.401 +
  27.402 +	/* Setup watches so we asynchronously connect to serial console */
  27.403 +	if (!(xs_watch(dom->xsh, dom->conspath, ""))) {
  27.404 +		fprintf(stderr, "Unable to watch console %s\n", dom->conspath);
  27.405 +		goto fail;
  27.406 +	}
  27.407 +	if (!(xs_watch(dom->xsh, dom->serialpath, ""))) {
  27.408 +		fprintf(stderr, "Unable to watch console %s\n", dom->conspath);
  27.409 +		xs_unwatch(dom->xsh, dom->conspath, "");
  27.410 +		goto fail;
  27.411 +	}
  27.412 +	qemu_set_fd_handler2(xs_fileno(dom->xsh), NULL, xencons_startup, NULL, dom);
  27.413 +	fprintf(stderr, "Console: prepared domain, waiting for ringref at %s or %s\n",
  27.414 +		dom->conspath, dom->serialpath);
  27.415 +
  27.416 +	return 0;
  27.417 +
  27.418 +fail:
  27.419 +	xs_daemon_close(dom->xsh);
  27.420 +	free(dom->serialpath);
  27.421 +	free(dom->conspath);
  27.422 +	free(dom);
  27.423 +	return -1;
  27.424 +}
  27.425 +
  27.426 +
  27.427 +/*
  27.428 + * Local variables:
  27.429 + *  c-file-style: "linux"
  27.430 + *  indent-tabs-mode: t
  27.431 + *  c-indent-level: 8
  27.432 + *  c-basic-offset: 8
  27.433 + *  tab-width: 8
  27.434 + * End:
  27.435 + */
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/ioemu/hw/xen_console.h	Tue Oct 30 15:34:44 2007 -0600
    28.3 @@ -0,0 +1,25 @@
    28.4 +/*
    28.5 + *  Copyright (C) International Business Machines  Corp., 2005
    28.6 + *  Author(s): Anthony Liguori <aliguori@us.ibm.com>
    28.7 + *
    28.8 + *  Copyright (C) Red Hat 2007
    28.9 + *
   28.10 + *  Xen Console
   28.11 + *
   28.12 + *  This program is free software; you can redistribute it and/or modify
   28.13 + *  it under the terms of the GNU General Public License as published by
   28.14 + *  the Free Software Foundation; under version 2 of the License.
   28.15 + * 
   28.16 + *  This program is distributed in the hope that it will be useful,
   28.17 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.18 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.19 + *  GNU General Public License for more details.
   28.20 + * 
   28.21 + *  You should have received a copy of the GNU General Public License
   28.22 + *  along with this program; if not, write to the Free Software
   28.23 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.24 + */
   28.25 +
   28.26 +#include "vl.h"
   28.27 +
   28.28 +extern int xencons_init(int domid, CharDriverState *chr);
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/ioemu/hw/xen_machine_fv.c	Tue Oct 30 15:34:44 2007 -0600
    29.3 @@ -0,0 +1,296 @@
    29.4 +/*
    29.5 + * QEMU Xen FV Machine
    29.6 + *
    29.7 + * Copyright (c) 2003-2007 Fabrice Bellard
    29.8 + * Copyright (c) 2007 Red Hat
    29.9 + *
   29.10 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   29.11 + * of this software and associated documentation files (the "Software"), to deal
   29.12 + * in the Software without restriction, including without limitation the rights
   29.13 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   29.14 + * copies of the Software, and to permit persons to whom the Software is
   29.15 + * furnished to do so, subject to the following conditions:
   29.16 + *
   29.17 + * The above copyright notice and this permission notice shall be included in
   29.18 + * all copies or substantial portions of the Software.
   29.19 + *
   29.20 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   29.21 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   29.22 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   29.23 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   29.24 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   29.25 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   29.26 + * THE SOFTWARE.
   29.27 + */
   29.28 +
   29.29 +#include "vl.h"
   29.30 +#include <xen/hvm/params.h>
   29.31 +#include <sys/mman.h>
   29.32 +
   29.33 +#ifndef PAGE_SIZE
   29.34 +#define PAGE_SIZE XC_PAGE_SIZE
   29.35 +#endif
   29.36 +#ifndef PAGE_SHIFT
   29.37 +#define PAGE_SHIFT XC_PAGE_SHIFT
   29.38 +#endif
   29.39 +
   29.40 +#if defined(MAPCACHE)
   29.41 +
   29.42 +#if defined(__i386__) 
   29.43 +#define MAX_MCACHE_SIZE    0x40000000 /* 1GB max for x86 */
   29.44 +#define MCACHE_BUCKET_SHIFT 16
   29.45 +#elif defined(__x86_64__)
   29.46 +#define MAX_MCACHE_SIZE    0x1000000000 /* 64GB max for x86_64 */
   29.47 +#define MCACHE_BUCKET_SHIFT 20
   29.48 +#endif
   29.49 +
   29.50 +#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
   29.51 +
   29.52 +#define BITS_PER_LONG (sizeof(long)*8)
   29.53 +#define BITS_TO_LONGS(bits) \
   29.54 +    (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
   29.55 +#define DECLARE_BITMAP(name,bits) \
   29.56 +    unsigned long name[BITS_TO_LONGS(bits)]
   29.57 +#define test_bit(bit,map) \
   29.58 +    (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG))))
   29.59 +
   29.60 +struct map_cache {
   29.61 +    unsigned long paddr_index;
   29.62 +    uint8_t      *vaddr_base;
   29.63 +    DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT);
   29.64 +};
   29.65 +
   29.66 +static struct map_cache *mapcache_entry;
   29.67 +static unsigned long nr_buckets;
   29.68 +
   29.69 +/* For most cases (>99.9%), the page address is the same. */
   29.70 +static unsigned long last_address_index = ~0UL;
   29.71 +static uint8_t      *last_address_vaddr;
   29.72 +
   29.73 +static int qemu_map_cache_init(void)
   29.74 +{
   29.75 +    unsigned long size;
   29.76 +
   29.77 +    nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
   29.78 +                   (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
   29.79 +                  (MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
   29.80 +
   29.81 +    /*
   29.82 +     * Use mmap() directly: lets us allocate a big hash table with no up-front
   29.83 +     * cost in storage space. The OS will allocate memory only for the buckets
   29.84 +     * that we actually use. All others will contain all zeroes.
   29.85 +     */
   29.86 +    size = nr_buckets * sizeof(struct map_cache);
   29.87 +    size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
   29.88 +    fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n", nr_buckets, size);
   29.89 +    mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
   29.90 +                          MAP_SHARED|MAP_ANON, -1, 0);
   29.91 +    if (mapcache_entry == MAP_FAILED) {
   29.92 +        errno = ENOMEM;
   29.93 +        return -1;
   29.94 +    }
   29.95 +
   29.96 +    return 0;
   29.97 +}
   29.98 +
   29.99 +static void qemu_remap_bucket(struct map_cache *entry,
  29.100 +                              unsigned long address_index)
  29.101 +{
  29.102 +    uint8_t *vaddr_base;
  29.103 +    unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT];
  29.104 +    unsigned int i, j;
  29.105 +
  29.106 +    if (entry->vaddr_base != NULL) {
  29.107 +        errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
  29.108 +        if (errno) {
  29.109 +            fprintf(logfile, "unmap fails %d\n", errno);
  29.110 +            exit(-1);
  29.111 +        }
  29.112 +    }
  29.113 +
  29.114 +    for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++)
  29.115 +        pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i;
  29.116 +
  29.117 +    vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE,
  29.118 +                                      pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT);
  29.119 +    if (vaddr_base == NULL) {
  29.120 +        fprintf(logfile, "xc_map_foreign_batch error %d\n", errno);
  29.121 +        exit(-1);
  29.122 +    }
  29.123 +
  29.124 +    entry->vaddr_base  = vaddr_base;
  29.125 +    entry->paddr_index = address_index;
  29.126 +
  29.127 +    for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) {
  29.128 +        unsigned long word = 0;
  29.129 +        j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ?
  29.130 +            (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;
  29.131 +        while (j > 0)
  29.132 +            word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf);
  29.133 +        entry->valid_mapping[i / BITS_PER_LONG] = word;
  29.134 +    }
  29.135 +}
  29.136 +
  29.137 +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr)
  29.138 +{
  29.139 +    struct map_cache *entry;
  29.140 +    unsigned long address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
  29.141 +    unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1);
  29.142 +
  29.143 +    if (address_index == last_address_index)
  29.144 +        return last_address_vaddr + address_offset;
  29.145 +
  29.146 +    entry = &mapcache_entry[address_index % nr_buckets];
  29.147 +
  29.148 +    if (entry->vaddr_base == NULL || entry->paddr_index != address_index ||
  29.149 +        !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
  29.150 +        qemu_remap_bucket(entry, address_index);
  29.151 +
  29.152 +    if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
  29.153 +        return NULL;
  29.154 +
  29.155 +    last_address_index = address_index;
  29.156 +    last_address_vaddr = entry->vaddr_base;
  29.157 +
  29.158 +    return last_address_vaddr + address_offset;
  29.159 +}
  29.160 +
  29.161 +void qemu_invalidate_map_cache(void)
  29.162 +{
  29.163 +    unsigned long i;
  29.164 +
  29.165 +    mapcache_lock();
  29.166 +
  29.167 +    for (i = 0; i < nr_buckets; i++) {
  29.168 +        struct map_cache *entry = &mapcache_entry[i];
  29.169 +
  29.170 +        if (entry->vaddr_base == NULL)
  29.171 +            continue;
  29.172 +
  29.173 +        errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
  29.174 +        if (errno) {
  29.175 +            fprintf(logfile, "unmap fails %d\n", errno);
  29.176 +            exit(-1);
  29.177 +        }
  29.178 +
  29.179 +        entry->paddr_index = 0;
  29.180 +        entry->vaddr_base  = NULL;
  29.181 +    }
  29.182 +
  29.183 +    last_address_index =  ~0UL;
  29.184 +    last_address_vaddr = NULL;
  29.185 +
  29.186 +    mapcache_unlock();
  29.187 +}
  29.188 +
  29.189 +#endif /* defined(MAPCACHE) */
  29.190 +
  29.191 +
  29.192 +static void xen_init_fv(uint64_t ram_size, int vga_ram_size, char *boot_device,
  29.193 +                        DisplayState *ds, const char **fd_filename,
  29.194 +                        int snapshot,
  29.195 +                        const char *kernel_filename,
  29.196 +                        const char *kernel_cmdline,
  29.197 +                        const char *initrd_filename,
  29.198 +                        const char *direct_pci)
  29.199 +{
  29.200 +    unsigned long ioreq_pfn;
  29.201 +    extern void *shared_page;
  29.202 +    extern void *buffered_io_page;
  29.203 +#ifdef __ia64__
  29.204 +    unsigned long nr_pages;
  29.205 +    xen_pfn_t *page_array;
  29.206 +    extern void *buffered_pio_page;
  29.207 +    int i;
  29.208 +#endif
  29.209 +
  29.210 +#if defined(__i386__) || defined(__x86_64__)
  29.211 +
  29.212 +    if (qemu_map_cache_init()) {
  29.213 +        fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno);
  29.214 +        exit(-1);
  29.215 +    }
  29.216 +
  29.217 +    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
  29.218 +    fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn);
  29.219 +    shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  29.220 +                                       PROT_READ|PROT_WRITE, ioreq_pfn);
  29.221 +    if (shared_page == NULL) {
  29.222 +        fprintf(logfile, "map shared IO page returned error %d\n", errno);
  29.223 +        exit(-1);
  29.224 +    }
  29.225 +
  29.226 +    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
  29.227 +    fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
  29.228 +    buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  29.229 +                                            PROT_READ|PROT_WRITE, ioreq_pfn);
  29.230 +    if (buffered_io_page == NULL) {
  29.231 +        fprintf(logfile, "map buffered IO page returned error %d\n", errno);
  29.232 +        exit(-1);
  29.233 +    }
  29.234 +
  29.235 +#elif defined(__ia64__)
  29.236 +
  29.237 +    nr_pages = ram_size/PAGE_SIZE;
  29.238 +
  29.239 +    page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t));
  29.240 +    if (page_array == NULL) {
  29.241 +        fprintf(logfile, "malloc returned error %d\n", errno);
  29.242 +        exit(-1);
  29.243 +    }
  29.244 +
  29.245 +    shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  29.246 +                                       PROT_READ|PROT_WRITE,
  29.247 +                                       IO_PAGE_START >> PAGE_SHIFT);
  29.248 +
  29.249 +    buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  29.250 +                                       PROT_READ|PROT_WRITE,
  29.251 +                                       BUFFER_IO_PAGE_START >> PAGE_SHIFT);
  29.252 +
  29.253 +    buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  29.254 +                                       PROT_READ|PROT_WRITE,
  29.255 +                                       BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
  29.256 +
  29.257 +    for (i = 0; i < nr_pages; i++)
  29.258 +        page_array[i] = i;
  29.259 +	
  29.260 +    /* VTI will not use memory between 3G~4G, so we just pass a legal pfn
  29.261 +       to make QEMU map continuous virtual memory space */
  29.262 +    if (ram_size > MMIO_START) {	
  29.263 +        for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++)
  29.264 +            page_array[(MMIO_START >> PAGE_SHIFT) + i] =
  29.265 +                (STORE_PAGE_START >> PAGE_SHIFT); 
  29.266 +    }
  29.267 +
  29.268 +    phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
  29.269 +                                         PROT_READ|PROT_WRITE,
  29.270 +                                         page_array, nr_pages);
  29.271 +    if (phys_ram_base == 0) {
  29.272 +        fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
  29.273 +        exit(-1);
  29.274 +    }
  29.275 +    free(page_array);
  29.276 +#endif
  29.277 +
  29.278 +    timeoffset_get();
  29.279 +
  29.280 +
  29.281 +    pc_machine.init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
  29.282 +                    snapshot, kernel_filename, kernel_cmdline, initrd_filename,
  29.283 +                    direct_pci);
  29.284 +}
  29.285 +
  29.286 +QEMUMachine xenfv_machine = {
  29.287 +    "xenfv",
  29.288 +    "Xen Fully-virtualized PC",
  29.289 +    xen_init_fv,
  29.290 +};
  29.291 +
  29.292 +/*
  29.293 + * Local variables:
  29.294 + *  indent-tabs-mode: nil
  29.295 + *  c-indent-level: 4
  29.296 + *  c-basic-offset: 4
  29.297 + *  tab-width: 4
  29.298 + * End:
  29.299 + */
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/tools/ioemu/hw/xen_machine_pv.c	Tue Oct 30 15:34:44 2007 -0600
    30.3 @@ -0,0 +1,73 @@
    30.4 +/*
    30.5 + * QEMU Xen PV Machine
    30.6 + *
    30.7 + * Copyright (c) 2007 Red Hat
    30.8 + *
    30.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   30.10 + * of this software and associated documentation files (the "Software"), to deal
   30.11 + * in the Software without restriction, including without limitation the rights
   30.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   30.13 + * copies of the Software, and to permit persons to whom the Software is
   30.14 + * furnished to do so, subject to the following conditions:
   30.15 + *
   30.16 + * The above copyright notice and this permission notice shall be included in
   30.17 + * all copies or substantial portions of the Software.
   30.18 + *
   30.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   30.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   30.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   30.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   30.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   30.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   30.25 + * THE SOFTWARE.
   30.26 + */
   30.27 +
   30.28 +#include "vl.h"
   30.29 +#include "xen_console.h"
   30.30 +#include "xenfb.h"
   30.31 +
   30.32 +/* The Xen PV machine currently provides
   30.33 + *   - a virtual framebuffer
   30.34 + *   - ....
   30.35 + */
   30.36 +static void xen_init_pv(uint64_t ram_size, int vga_ram_size, char *boot_device,
   30.37 +			DisplayState *ds, const char **fd_filename,
   30.38 +			int snapshot,
   30.39 +			const char *kernel_filename,
   30.40 +			const char *kernel_cmdline,
   30.41 +			const char *initrd_filename)
   30.42 +{
   30.43 +    struct xenfb *xenfb;
   30.44 +    extern int domid;
   30.45 +
   30.46 +    /* Connect to text console */
   30.47 +    if (serial_hds[0]) {
   30.48 +        if (xencons_init(domid, serial_hds[0]) < 0) {
   30.49 +            fprintf(stderr, "Could not connect to domain console\n");
   30.50 +            exit(1);
   30.51 +        }
   30.52 +    }
   30.53 +
   30.54 +    /* Prepare PVFB state */
   30.55 +    xenfb = xenfb_new(domid, ds);
   30.56 +    if (xenfb == NULL) {
   30.57 +        fprintf(stderr, "Could not create framebuffer (%s)\n",
   30.58 +                strerror(errno));
   30.59 +        exit(1);
   30.60 +    }
   30.61 +}
   30.62 +
   30.63 +QEMUMachine xenpv_machine = {
   30.64 +    "xenpv",
   30.65 +    "Xen Para-virtualized PC",
   30.66 +    xen_init_pv,
   30.67 +};
   30.68 +
   30.69 +/*
   30.70 + * Local variables:
   30.71 + *  indent-tabs-mode: nil
   30.72 + *  c-indent-level: 4
   30.73 + *  c-basic-offset: 4
   30.74 + *  tab-width: 4
   30.75 + * End:
   30.76 + */
    31.1 --- a/tools/ioemu/hw/xen_platform.c	Tue Oct 30 11:33:55 2007 -0600
    31.2 +++ b/tools/ioemu/hw/xen_platform.c	Tue Oct 30 15:34:44 2007 -0600
    31.3 @@ -36,14 +36,24 @@ static void platform_ioport_map(PCIDevic
    31.4  
    31.5  static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
    31.6  {
    31.7 -    fprintf(logfile, "Warning: try read from xen platform mmio space\n");
    31.8 +    static int warnings = 0;
    31.9 +    if (warnings < 5) {
   31.10 +	    fprintf(logfile, "Warning: attempted read from physical address "
   31.11 +		    "0x%lx in xen platform mmio space\n", addr);
   31.12 +	    warnings++;
   31.13 +    }
   31.14      return 0;
   31.15  }
   31.16  
   31.17  static void platform_mmio_write(void *opaque, target_phys_addr_t addr,
   31.18  			       uint32_t val)
   31.19  {
   31.20 -    fprintf(logfile, "Warning: try write to xen platform mmio space\n");
   31.21 +    static int warnings = 0;
   31.22 +    if (warnings < 5) {
   31.23 +	    fprintf(logfile, "Warning: attempted write of 0x%x to physical "
   31.24 +		    "address 0x%lx in xen platform mmio space\n", val, addr);
   31.25 +	    warnings++;
   31.26 +    }
   31.27      return;
   31.28  }
   31.29  
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/ioemu/hw/xenfb.c	Tue Oct 30 15:34:44 2007 -0600
    32.3 @@ -0,0 +1,1157 @@
    32.4 +#include <stdarg.h>
    32.5 +#include <stdlib.h>
    32.6 +#include <sys/types.h>
    32.7 +#include <fcntl.h>
    32.8 +#include <unistd.h>
    32.9 +#include <xenctrl.h>
   32.10 +#include <xen/io/xenbus.h>
   32.11 +#include <xen/io/fbif.h>
   32.12 +#include <xen/io/kbdif.h>
   32.13 +#include <xen/io/protocols.h>
   32.14 +#include <stdbool.h>
   32.15 +#include <xen/event_channel.h>
   32.16 +#include <sys/mman.h>
   32.17 +#include <errno.h>
   32.18 +#include <stdio.h>
   32.19 +#include <string.h>
   32.20 +#include <time.h>
   32.21 +#include <xs.h>
   32.22 +#include <linux/input.h>
   32.23 +
   32.24 +#include "xenfb.h"
   32.25 +
   32.26 +// FIXME defend against malicious frontend?
   32.27 +
   32.28 +struct xenfb;
   32.29 +
   32.30 +struct xenfb_device {
   32.31 +	const char *devicetype;
   32.32 +	char nodename[64];	/* backend xenstore dir */
   32.33 +	char otherend[64];	/* frontend xenstore dir */
   32.34 +	int otherend_id;	/* frontend domid */
   32.35 +	enum xenbus_state state; /* backend state */
   32.36 +	void *page;		/* shared page */
   32.37 +	evtchn_port_t port;
   32.38 +	struct xenfb *xenfb;
   32.39 +};
   32.40 +
   32.41 +struct xenfb {
   32.42 +	DisplayState *ds;       /* QEMU graphical console state */
   32.43 +	int evt_xch;		/* event channel driver handle */
   32.44 +	int xc;			/* hypervisor interface handle */
   32.45 +	struct xs_handle *xsh;	/* xs daemon handle */
   32.46 +	struct xenfb_device fb, kbd;
   32.47 +	void *pixels;           /* guest framebuffer data */
   32.48 +	size_t fb_len;		/* size of framebuffer */
   32.49 +	int row_stride;         /* width of one row in framebuffer */
   32.50 +	int depth;              /* colour depth of guest framebuffer */
   32.51 +	int width;              /* pixel width of guest framebuffer */
   32.52 +	int height;             /* pixel height of guest framebuffer */
   32.53 +	int abs_pointer_wanted; /* Whether guest supports absolute pointer */
   32.54 +	int button_state;       /* Last seen pointer button state */
   32.55 +	char protocol[64];	/* frontend protocol */
   32.56 +};
   32.57 +
   32.58 +/* Functions for frontend/backend state machine*/
   32.59 +static int xenfb_wait_for_frontend(struct xenfb_device *dev, IOHandler *handler);
   32.60 +static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler *handler);
   32.61 +static void xenfb_backend_created_kbd(void *opaque);
   32.62 +static void xenfb_backend_created_fb(void *opaque);
   32.63 +static void xenfb_frontend_initialized_kbd(void *opaque);
   32.64 +static void xenfb_frontend_initialized_fb(void *opaque);
   32.65 +static void xenfb_frontend_connected_kbd(void *opaque);
   32.66 +
   32.67 +/* Helper functions for checking state of frontend/backend devices */
   32.68 +static int xenfb_frontend_connected(struct xenfb_device *dev);
   32.69 +static int xenfb_frontend_initialized(struct xenfb_device *dev);
   32.70 +static int xenfb_backend_created(struct xenfb_device *dev);
   32.71 +
   32.72 +/* Functions which tie the PVFB into the QEMU device model */
   32.73 +static void xenfb_key_event(void *opaque, int keycode);
   32.74 +static void xenfb_mouse_event(void *opaque,
   32.75 +			      int dx, int dy, int dz, int button_state);
   32.76 +static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h);
   32.77 +static void xenfb_update(void *opaque);
   32.78 +static void xenfb_invalidate(void *opaque);
   32.79 +static void xenfb_screen_dump(void *opaque, const char *name);
   32.80 +static int xenfb_register_console(struct xenfb *xenfb);
   32.81 +
   32.82 +/*
   32.83 + * Tables to map from scancode to Linux input layer keycode.
   32.84 + * Scancodes are hardware-specific.  These maps assumes a 
   32.85 + * standard AT or PS/2 keyboard which is what QEMU feeds us.
   32.86 + */
   32.87 +static const unsigned char atkbd_set2_keycode[512] = {
   32.88 +
   32.89 +	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
   32.90 +	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
   32.91 +	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
   32.92 +	  0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
   32.93 +	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
   32.94 +	  0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
   32.95 +	  0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
   32.96 +	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
   32.97 +
   32.98 +	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   32.99 +	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
  32.100 +	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
  32.101 +	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
  32.102 +	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
  32.103 +	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
  32.104 +	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
  32.105 +	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
  32.106 +
  32.107 +};
  32.108 +
  32.109 +static const unsigned char atkbd_unxlate_table[128] = {
  32.110 +
  32.111 +	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
  32.112 +	 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
  32.113 +	 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
  32.114 +	 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
  32.115 +	 11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
  32.116 +	114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
  32.117 +	 71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
  32.118 +	 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
  32.119 +
  32.120 +};
  32.121 +
  32.122 +static unsigned char scancode2linux[512];
  32.123 +
  32.124 +static int xenfb_xs_scanf1(struct xs_handle *xsh,
  32.125 +			   const char *dir, const char *node,
  32.126 +			   const char *fmt, void *dest)
  32.127 +{
  32.128 +	char buf[1024];
  32.129 +	char *p;
  32.130 +	int ret;
  32.131 +
  32.132 +	if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
  32.133 +		errno = ENOENT;
  32.134 +		return -1;
  32.135 +        }
  32.136 +	p = xs_read(xsh, XBT_NULL, buf, NULL);
  32.137 +	if (!p) {
  32.138 +		errno = ENOENT;
  32.139 +		return -1;
  32.140 +        }
  32.141 +	ret = sscanf(p, fmt, dest);
  32.142 +	free(p);
  32.143 +	if (ret != 1) {
  32.144 +		errno = EDOM;
  32.145 +		return -1;
  32.146 +        }
  32.147 +	return ret;
  32.148 +}
  32.149 +
  32.150 +static int xenfb_xs_printf(struct xs_handle *xsh,
  32.151 +			   const char *dir, const char *node, char *fmt, ...)
  32.152 +{
  32.153 +	va_list ap;
  32.154 +	char key[1024];
  32.155 +	char val[1024];
  32.156 +	int n;
  32.157 +
  32.158 +	if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
  32.159 +		errno = ENOENT;
  32.160 +		return -1;
  32.161 +        }
  32.162 +
  32.163 +	va_start(ap, fmt);
  32.164 +	n = vsnprintf(val, sizeof(val), fmt, ap);
  32.165 +	va_end(ap);
  32.166 +	if (n >= sizeof(val)) {
  32.167 +		errno = ENOSPC; /* close enough */
  32.168 +		return -1;
  32.169 +	}
  32.170 +
  32.171 +	if (!xs_write(xsh, XBT_NULL, key, val, n))
  32.172 +		return -1;
  32.173 +	return 0;
  32.174 +}
  32.175 +
  32.176 +static void xenfb_device_init(struct xenfb_device *dev,
  32.177 +			      const char *type,
  32.178 +			      struct xenfb *xenfb)
  32.179 +{
  32.180 +	dev->devicetype = type;
  32.181 +	dev->otherend_id = -1;
  32.182 +	dev->port = -1;
  32.183 +	dev->xenfb = xenfb;
  32.184 +}
  32.185 +
  32.186 +static char *xenfb_path_in_dom(struct xs_handle *xsh,
  32.187 +                               char *buf, size_t size,
  32.188 +                               unsigned domid, const char *fmt, ...)
  32.189 +{
  32.190 +        va_list ap;
  32.191 +        char *domp = xs_get_domain_path(xsh, domid);
  32.192 +        int n;
  32.193 +
  32.194 +        if (domp == NULL)
  32.195 +                return NULL;
  32.196 +
  32.197 +        n = snprintf(buf, size, "%s/", domp);
  32.198 +        free(domp);
  32.199 +        if (n >= size)
  32.200 +                return NULL;
  32.201 +
  32.202 +        va_start(ap, fmt);
  32.203 +        n += vsnprintf(buf + n, size - n, fmt, ap);
  32.204 +        va_end(ap);
  32.205 +        if (n >= size)
  32.206 +                return NULL;
  32.207 +
  32.208 +        return buf;
  32.209 +}
  32.210 +
  32.211 +static int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
  32.212 +{
  32.213 +        dev->otherend_id = domid;
  32.214 +
  32.215 +        if (!xenfb_path_in_dom(dev->xenfb->xsh,
  32.216 +                               dev->otherend, sizeof(dev->otherend),
  32.217 +                               domid, "device/%s/0", dev->devicetype)) {
  32.218 +                errno = ENOENT;
  32.219 +                return -1;
  32.220 +        }
  32.221 +        if (!xenfb_path_in_dom(dev->xenfb->xsh,
  32.222 +                               dev->nodename, sizeof(dev->nodename),
  32.223 +                               0, "backend/%s/%d/0", dev->devicetype, domid)) {
  32.224 +                errno = ENOENT;
  32.225 +                return -1;
  32.226 +        }
  32.227 +
  32.228 +        return 0;
  32.229 +}
  32.230 +
  32.231 +struct xenfb *xenfb_new(int domid, DisplayState *ds)
  32.232 +{
  32.233 +	struct xenfb *xenfb = qemu_malloc(sizeof(struct xenfb));
  32.234 +	int serrno;
  32.235 +	int i;
  32.236 +
  32.237 +	if (xenfb == NULL)
  32.238 +		return NULL;
  32.239 +
  32.240 +	/* Prepare scancode mapping table */
  32.241 +	for (i = 0; i < 128; i++) {
  32.242 +		scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
  32.243 +		scancode2linux[i | 0x80] = 
  32.244 +			atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
  32.245 +	}
  32.246 +
  32.247 +	memset(xenfb, 0, sizeof(*xenfb));
  32.248 +	xenfb->evt_xch = xenfb->xc = -1;
  32.249 +	xenfb_device_init(&xenfb->fb, "vfb", xenfb);
  32.250 +	xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
  32.251 +
  32.252 +	xenfb->evt_xch = xc_evtchn_open();
  32.253 +	if (xenfb->evt_xch == -1)
  32.254 +		goto fail;
  32.255 +
  32.256 +	xenfb->xc = xc_interface_open();
  32.257 +	if (xenfb->xc == -1)
  32.258 +		goto fail;
  32.259 +
  32.260 +	xenfb->xsh = xs_daemon_open();
  32.261 +	if (!xenfb->xsh)
  32.262 +		goto fail;
  32.263 +
  32.264 +	xenfb->ds = ds;
  32.265 +	xenfb_device_set_domain(&xenfb->fb, domid);
  32.266 +	xenfb_device_set_domain(&xenfb->kbd, domid);
  32.267 +
  32.268 +	fprintf(stderr, "FB: Waiting for KBD backend creation\n");
  32.269 +	xenfb_wait_for_backend(&xenfb->kbd, xenfb_backend_created_kbd);
  32.270 +
  32.271 +	return xenfb;
  32.272 +
  32.273 + fail:
  32.274 +	serrno = errno;
  32.275 +	xenfb_shutdown(xenfb);
  32.276 +	errno = serrno;
  32.277 +	return NULL;
  32.278 +}
  32.279 +
  32.280 +
  32.281 +static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
  32.282 +					  const char *dir)
  32.283 +{
  32.284 +	int ret, state;
  32.285 +
  32.286 +	ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
  32.287 +	if (ret < 0)
  32.288 +		return XenbusStateUnknown;
  32.289 +
  32.290 +	if ((unsigned)state > XenbusStateClosed)
  32.291 +		state = XenbusStateUnknown;
  32.292 +	return state;
  32.293 +}
  32.294 +
  32.295 +static int xenfb_switch_state(struct xenfb_device *dev,
  32.296 +			      enum xenbus_state state)
  32.297 +{
  32.298 +	struct xs_handle *xsh = dev->xenfb->xsh;
  32.299 +
  32.300 +	if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
  32.301 +		return -1;
  32.302 +	dev->state = state;
  32.303 +	return 0;
  32.304 +}
  32.305 +
  32.306 +
  32.307 +static int xenfb_hotplug(struct xenfb_device *dev)
  32.308 +{
  32.309 +	if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
  32.310 +			    "hotplug-status", "connected"))
  32.311 +		return -1;
  32.312 +	return 0;
  32.313 +}
  32.314 +
  32.315 +static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
  32.316 +{
  32.317 +	uint32_t *src32 = src;
  32.318 +	uint64_t *src64 = src;
  32.319 +	int i;
  32.320 +
  32.321 +	for (i = 0; i < count; i++)
  32.322 +		dst[i] = (mode == 32) ? src32[i] : src64[i];
  32.323 +}
  32.324 +
  32.325 +static int xenfb_map_fb(struct xenfb *xenfb, int domid)
  32.326 +{
  32.327 +	struct xenfb_page *page = xenfb->fb.page;
  32.328 +	int n_fbmfns;
  32.329 +	int n_fbdirs;
  32.330 +	unsigned long *pgmfns = NULL;
  32.331 +	unsigned long *fbmfns = NULL;
  32.332 +	void *map, *pd;
  32.333 +	int mode, ret = -1;
  32.334 +
  32.335 +	/* default to native */
  32.336 +	pd = page->pd;
  32.337 +	mode = sizeof(unsigned long) * 8;
  32.338 +
  32.339 +	if (0 == strlen(xenfb->protocol)) {
  32.340 +		/*
  32.341 +		 * Undefined protocol, some guesswork needed.
  32.342 +		 *
  32.343 +		 * Old frontends which don't set the protocol use
  32.344 +		 * one page directory only, thus pd[1] must be zero.
  32.345 +		 * pd[1] of the 32bit struct layout and the lower
  32.346 +		 * 32 bits of pd[0] of the 64bit struct layout have
  32.347 +		 * the same location, so we can check that ...
  32.348 +		 */
  32.349 +		uint32_t *ptr32 = NULL;
  32.350 +		uint32_t *ptr64 = NULL;
  32.351 +#if defined(__i386__)
  32.352 +		ptr32 = (void*)page->pd;
  32.353 +		ptr64 = ((void*)page->pd) + 4;
  32.354 +#elif defined(__x86_64__)
  32.355 +		ptr32 = ((void*)page->pd) - 4;
  32.356 +		ptr64 = (void*)page->pd;
  32.357 +#endif
  32.358 +		if (ptr32) {
  32.359 +			if (0 == ptr32[1]) {
  32.360 +				mode = 32;
  32.361 +				pd   = ptr32;
  32.362 +			} else {
  32.363 +				mode = 64;
  32.364 +				pd   = ptr64;
  32.365 +			}
  32.366 +		}
  32.367 +#if defined(__x86_64__)
  32.368 +	} else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
  32.369 +		/* 64bit dom0, 32bit domU */
  32.370 +		mode = 32;
  32.371 +		pd   = ((void*)page->pd) - 4;
  32.372 +#elif defined(__i386__)
  32.373 +	} else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
  32.374 +		/* 32bit dom0, 64bit domU */
  32.375 +		mode = 64;
  32.376 +		pd   = ((void*)page->pd) + 4;
  32.377 +#endif
  32.378 +	}
  32.379 +
  32.380 +	n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
  32.381 +	n_fbdirs = n_fbmfns * mode / 8;
  32.382 +	n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
  32.383 +
  32.384 +	pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
  32.385 +	fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
  32.386 +	if (!pgmfns || !fbmfns)
  32.387 +		goto out;
  32.388 +
  32.389 +	xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
  32.390 +	map = xc_map_foreign_pages(xenfb->xc, domid,
  32.391 +				   PROT_READ, pgmfns, n_fbdirs);
  32.392 +	if (map == NULL)
  32.393 +		goto out;
  32.394 +	xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
  32.395 +	munmap(map, n_fbdirs * XC_PAGE_SIZE);
  32.396 +
  32.397 +	xenfb->pixels = xc_map_foreign_pages(xenfb->xc, domid,
  32.398 +				PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
  32.399 +	if (xenfb->pixels == NULL)
  32.400 +		goto out;
  32.401 +
  32.402 +	ret = 0; /* all is fine */
  32.403 +
  32.404 + out:
  32.405 +	if (pgmfns)
  32.406 +		free(pgmfns);
  32.407 +	if (fbmfns)
  32.408 +		free(fbmfns);
  32.409 +	return ret;
  32.410 +}
  32.411 +
  32.412 +static int xenfb_bind(struct xenfb_device *dev)
  32.413 +{
  32.414 +	struct xenfb *xenfb = dev->xenfb;
  32.415 +	unsigned long mfn;
  32.416 +	evtchn_port_t evtchn;
  32.417 +
  32.418 +	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
  32.419 +			    &mfn) < 0)
  32.420 +		return -1;
  32.421 +	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
  32.422 +			    &evtchn) < 0)
  32.423 +		return -1;
  32.424 +
  32.425 +	dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
  32.426 +					       dev->otherend_id, evtchn);
  32.427 +	if (dev->port == -1)
  32.428 +		return -1;
  32.429 +
  32.430 +	dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
  32.431 +			XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
  32.432 +	if (dev->page == NULL)
  32.433 +		return -1;
  32.434 +
  32.435 +	return 0;
  32.436 +}
  32.437 +
  32.438 +static void xenfb_unbind(struct xenfb_device *dev)
  32.439 +{
  32.440 +	if (dev->page) {
  32.441 +		munmap(dev->page, XC_PAGE_SIZE);
  32.442 +		dev->page = NULL;
  32.443 +	}
  32.444 +        if (dev->port >= 0) {
  32.445 +		xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
  32.446 +		dev->port = -1;
  32.447 +	}
  32.448 +}
  32.449 +
  32.450 +
  32.451 +static void xenfb_detach_dom(struct xenfb *xenfb)
  32.452 +{
  32.453 +	xenfb_unbind(&xenfb->fb);
  32.454 +	xenfb_unbind(&xenfb->kbd);
  32.455 +	if (xenfb->pixels) {
  32.456 +		munmap(xenfb->pixels, xenfb->fb_len);
  32.457 +		xenfb->pixels = NULL;
  32.458 +	}
  32.459 +}
  32.460 +
  32.461 +/* Remove the backend area in xenbus since the framebuffer really is
  32.462 +   going away. */
  32.463 +void xenfb_shutdown(struct xenfb *xenfb)
  32.464 +{
  32.465 +	fprintf(stderr, "FB: Shutting down backend\n");
  32.466 +	xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
  32.467 +	xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
  32.468 +
  32.469 +	xenfb_detach_dom(xenfb);
  32.470 +	if (xenfb->xc >= 0)
  32.471 +		xc_interface_close(xenfb->xc);
  32.472 +	if (xenfb->evt_xch >= 0)
  32.473 +		xc_evtchn_close(xenfb->evt_xch);
  32.474 +	if (xenfb->xsh)
  32.475 +		xs_daemon_close(xenfb->xsh);
  32.476 +	free(xenfb);
  32.477 +}
  32.478 +
  32.479 +
  32.480 +static void xenfb_on_fb_event(struct xenfb *xenfb)
  32.481 +{
  32.482 +	uint32_t prod, cons;
  32.483 +	struct xenfb_page *page = xenfb->fb.page;
  32.484 +
  32.485 +	prod = page->out_prod;
  32.486 +	if (prod == page->out_cons)
  32.487 +		return;
  32.488 +	rmb();			/* ensure we see ring contents up to prod */
  32.489 +	for (cons = page->out_cons; cons != prod; cons++) {
  32.490 +		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
  32.491 +
  32.492 +		switch (event->type) {
  32.493 +		case XENFB_TYPE_UPDATE:
  32.494 +			xenfb_guest_copy(xenfb,
  32.495 +					 event->update.x, event->update.y,
  32.496 +					 event->update.width, event->update.height);
  32.497 +			break;
  32.498 +		}
  32.499 +	}
  32.500 +	mb();			/* ensure we're done with ring contents */
  32.501 +	page->out_cons = cons;
  32.502 +	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
  32.503 +}
  32.504 +
  32.505 +static void xenfb_on_kbd_event(struct xenfb *xenfb)
  32.506 +{
  32.507 +	struct xenkbd_page *page = xenfb->kbd.page;
  32.508 +
  32.509 +	/* We don't understand any keyboard events, so just ignore them. */
  32.510 +	if (page->out_prod == page->out_cons)
  32.511 +		return;
  32.512 +	page->out_cons = page->out_prod;
  32.513 +	xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
  32.514 +}
  32.515 +
  32.516 +static int xenfb_on_state_change(struct xenfb_device *dev)
  32.517 +{
  32.518 +	enum xenbus_state state;
  32.519 +
  32.520 +	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
  32.521 +
  32.522 +	switch (state) {
  32.523 +	case XenbusStateUnknown:
  32.524 +		/* There was an error reading the frontend state.  The
  32.525 +		   domain has probably gone away; in any case, there's
  32.526 +		   not much point in us continuing. */
  32.527 +		return -1;
  32.528 +	case XenbusStateInitialising:
  32.529 +	case XenbusStateInitWait:
  32.530 +	case XenbusStateInitialised:
  32.531 +	case XenbusStateConnected:
  32.532 +		break;
  32.533 +	case XenbusStateClosing:
  32.534 +		xenfb_unbind(dev);
  32.535 +		xenfb_switch_state(dev, state);
  32.536 +		break;
  32.537 +	case XenbusStateClosed:
  32.538 +		xenfb_switch_state(dev, state);
  32.539 +	}
  32.540 +	return 0;
  32.541 +}
  32.542 +
  32.543 +/* Send an event to the keyboard frontend driver */
  32.544 +static int xenfb_kbd_event(struct xenfb *xenfb,
  32.545 +			   union xenkbd_in_event *event)
  32.546 +{
  32.547 +	uint32_t prod;
  32.548 +	struct xenkbd_page *page = xenfb->kbd.page;
  32.549 +
  32.550 +	if (xenfb->kbd.state != XenbusStateConnected)
  32.551 +		return 0;
  32.552 +
  32.553 +	prod = page->in_prod;
  32.554 +	if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
  32.555 +		errno = EAGAIN;
  32.556 +		return -1;
  32.557 +	}
  32.558 +
  32.559 +	mb();			/* ensure ring space available */
  32.560 +	XENKBD_IN_RING_REF(page, prod) = *event;
  32.561 +	wmb();			/* ensure ring contents visible */
  32.562 +	page->in_prod = prod + 1;
  32.563 +	return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
  32.564 +}
  32.565 +
  32.566 +/* Send a keyboard (or mouse button) event */
  32.567 +static int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode)
  32.568 +{
  32.569 +	union xenkbd_in_event event;
  32.570 +
  32.571 +	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
  32.572 +	event.type = XENKBD_TYPE_KEY;
  32.573 +	event.key.pressed = down ? 1 : 0;
  32.574 +	event.key.keycode = keycode;
  32.575 +
  32.576 +	return xenfb_kbd_event(xenfb, &event);
  32.577 +}
  32.578 +
  32.579 +/* Send a relative mouse movement event */
  32.580 +static int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y)
  32.581 +{
  32.582 +	union xenkbd_in_event event;
  32.583 +
  32.584 +	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
  32.585 +	event.type = XENKBD_TYPE_MOTION;
  32.586 +	event.motion.rel_x = rel_x;
  32.587 +	event.motion.rel_y = rel_y;
  32.588 +
  32.589 +	return xenfb_kbd_event(xenfb, &event);
  32.590 +}
  32.591 +
  32.592 +/* Send an absolute mouse movement event */
  32.593 +static int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y)
  32.594 +{
  32.595 +	union xenkbd_in_event event;
  32.596 +
  32.597 +	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
  32.598 +	event.type = XENKBD_TYPE_POS;
  32.599 +	event.pos.abs_x = abs_x;
  32.600 +	event.pos.abs_y = abs_y;
  32.601 +
  32.602 +	return xenfb_kbd_event(xenfb, &event);
  32.603 +}
  32.604 +
  32.605 +/* Process events from the frontend event channel */
  32.606 +static void xenfb_dispatch_channel(void *opaque)
  32.607 +{
  32.608 +	struct xenfb *xenfb = (struct xenfb *)opaque;
  32.609 +	evtchn_port_t port;
  32.610 +	port = xc_evtchn_pending(xenfb->evt_xch);
  32.611 +	if (port == -1) {
  32.612 +		xenfb_shutdown(xenfb);
  32.613 +		exit(1);
  32.614 +	}
  32.615 +
  32.616 +	if (port == xenfb->fb.port)
  32.617 +		xenfb_on_fb_event(xenfb);
  32.618 +	else if (port == xenfb->kbd.port)
  32.619 +		xenfb_on_kbd_event(xenfb);
  32.620 +
  32.621 +	if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) {
  32.622 +		xenfb_shutdown(xenfb);
  32.623 +		exit(1);
  32.624 +	}
  32.625 +}
  32.626 +
  32.627 +/* Process ongoing events from the frontend devices */
  32.628 +static void xenfb_dispatch_store(void *opaque)
  32.629 +{
  32.630 +	struct xenfb *xenfb = (struct xenfb *)opaque;
  32.631 +	unsigned dummy;
  32.632 +	char **vec;
  32.633 +	int r;
  32.634 +
  32.635 +	vec = xs_read_watch(xenfb->xsh, &dummy);
  32.636 +	free(vec);
  32.637 +	r = xenfb_on_state_change(&xenfb->fb);
  32.638 +	if (r == 0)
  32.639 +		r = xenfb_on_state_change(&xenfb->kbd);
  32.640 +	if (r < 0) {
  32.641 +		xenfb_shutdown(xenfb);
  32.642 +		exit(1);
  32.643 +	}
  32.644 +}
  32.645 +
  32.646 +
  32.647 +/****************************************************************
  32.648 + *
  32.649 + * Functions for processing frontend config
  32.650 + *
  32.651 + ****************************************************************/
  32.652 +
  32.653 +
  32.654 +/* Process the frontend framebuffer config */
  32.655 +static int xenfb_read_frontend_fb_config(struct xenfb *xenfb) {
  32.656 +	struct xenfb_page *fb_page;
  32.657 +	int val;
  32.658 +
  32.659 +        if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "feature-update",
  32.660 +                            "%d", &val) < 0)
  32.661 +                val = 0;
  32.662 +        if (!val) {
  32.663 +                fprintf(stderr, "feature-update not supported\n");
  32.664 +                errno = ENOTSUP;
  32.665 +                return -1;
  32.666 +        }
  32.667 +        if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "protocol", "%63s",
  32.668 +                            xenfb->protocol) < 0)
  32.669 +                xenfb->protocol[0] = '\0';
  32.670 +        xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1");
  32.671 +
  32.672 +        /* TODO check for permitted ranges */
  32.673 +        fb_page = xenfb->fb.page;
  32.674 +        xenfb->depth = fb_page->depth;
  32.675 +        xenfb->width = fb_page->width;
  32.676 +        xenfb->height = fb_page->height;
  32.677 +        /* TODO check for consistency with the above */
  32.678 +        xenfb->fb_len = fb_page->mem_length;
  32.679 +        xenfb->row_stride = fb_page->line_length;
  32.680 +        fprintf(stderr, "Framebuffer depth %d width %d height %d line %d\n",
  32.681 +                fb_page->depth, fb_page->width, fb_page->height, fb_page->line_length);
  32.682 +        if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0)
  32.683 +		return -1;
  32.684 +
  32.685 +        if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))
  32.686 +                return -1;
  32.687 +        if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))
  32.688 +                return -1;
  32.689 +
  32.690 +	return 0;
  32.691 +}
  32.692 +
  32.693 +/* Process the frontend keyboard config */
  32.694 +static int xenfb_read_frontend_kbd_config(struct xenfb *xenfb)
  32.695 +{
  32.696 +	int val;
  32.697 +
  32.698 +	if (xenfb_xs_scanf1(xenfb->xsh, xenfb->kbd.otherend, "request-abs-pointer",
  32.699 +			    "%d", &val) < 0)
  32.700 +		val = 0;
  32.701 +	xenfb->abs_pointer_wanted = val;
  32.702 +
  32.703 +	return 0;
  32.704 +}
  32.705 +
  32.706 +
  32.707 +/****************************************************************
  32.708 + *
  32.709 + * Functions for frontend/backend state machine
  32.710 + *
  32.711 + ****************************************************************/
  32.712 +
  32.713 +/* Register a watch against a frontend device, and setup
  32.714 + * QEMU event loop to poll the xenstore FD for notification */
  32.715 +static int xenfb_wait_for_frontend(struct xenfb_device *dev, IOHandler *handler)
  32.716 +{
  32.717 +        fprintf(stderr, "Doing frontend watch on %s\n", dev->otherend);
  32.718 +	if (!xs_watch(dev->xenfb->xsh, dev->otherend, "")) {
  32.719 +		fprintf(stderr, "Watch for dev failed\n");
  32.720 +		return -1;
  32.721 +	}
  32.722 +
  32.723 +	if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler, NULL, dev) < 0)
  32.724 +		return -1;
  32.725 +
  32.726 +	return 0;
  32.727 +}
  32.728 +
  32.729 +/* Register a watch against a backend device, and setup
  32.730 + * QEMU event loop to poll the xenstore FD for notification */
  32.731 +static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler *handler)
  32.732 +{
  32.733 +	fprintf(stderr, "Doing backend watch on %s\n", dev->nodename);
  32.734 +	if (!xs_watch(dev->xenfb->xsh, dev->nodename, "")) {
  32.735 +		fprintf(stderr, "Watch for dev failed\n");
  32.736 +		return -1;
  32.737 +	}
  32.738 +
  32.739 +	if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler, NULL, dev) < 0)
  32.740 +		return -1;
  32.741 +
  32.742 +	return 0;
  32.743 +}
  32.744 +
  32.745 +/* Callback invoked while waiting for KBD backend to change
  32.746 + * to the created state */
  32.747 +static void xenfb_backend_created_kbd(void *opaque)
  32.748 +{
  32.749 +	struct xenfb_device *dev = (struct xenfb_device *)opaque;
  32.750 +	int ret = xenfb_backend_created(dev);
  32.751 +	if (ret < 0) {
  32.752 +		xenfb_shutdown(dev->xenfb);
  32.753 +		exit(1);
  32.754 +	}
  32.755 +	if (ret)
  32.756 +		return; /* Still waiting */
  32.757 +
  32.758 +	if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename, "feature-abs-pointer", "1")) {
  32.759 +		xenfb_shutdown(dev->xenfb);
  32.760 +		exit(1);
  32.761 +	}
  32.762 +
  32.763 +	fprintf(stderr, "FB: Waiting for FB backend creation\n");
  32.764 +	xenfb_wait_for_backend(&dev->xenfb->fb, xenfb_backend_created_fb);
  32.765 +}
  32.766 +
  32.767 +/* Callback invoked while waiting for FB backend to change
  32.768 + * to the created state */
  32.769 +static void xenfb_backend_created_fb(void *opaque)
  32.770 +{
  32.771 +	struct xenfb_device *dev = (struct xenfb_device *)opaque;
  32.772 +	int ret = xenfb_backend_created(dev);
  32.773 +	if (ret < 0) {
  32.774 +		xenfb_shutdown(dev->xenfb);
  32.775 +		exit(1);
  32.776 +	}
  32.777 +	if (ret)
  32.778 +		return; /* Still waiting */
  32.779 +
  32.780 +	fprintf(stderr, "FB: Waiting for KBD frontend initialization\n");
  32.781 +	xenfb_wait_for_frontend(&dev->xenfb->kbd, xenfb_frontend_initialized_kbd);
  32.782 +}
  32.783 +
  32.784 +/* Callback invoked while waiting for KBD frontend to change
  32.785 + * to the initialized state */
  32.786 +static void xenfb_frontend_initialized_kbd(void *opaque)
  32.787 +{
  32.788 +	struct xenfb_device *dev = (struct xenfb_device *)opaque;
  32.789 +	int ret = xenfb_frontend_initialized(dev);
  32.790 +	if (ret < 0) {
  32.791 +		xenfb_shutdown(dev->xenfb);
  32.792 +		exit(1);
  32.793 +	}
  32.794 +	if (ret)
  32.795 +		return; /* Still waiting */
  32.796 +
  32.797 +
  32.798 +        fprintf(stderr, "FB: Waiting for FB frontend initialization\n");
  32.799 +	xenfb_wait_for_frontend(&dev->xenfb->fb, xenfb_frontend_initialized_fb);
  32.800 +}
  32.801 +
  32.802 +/* Callback invoked while waiting for FB frontend to change
  32.803 + * to the initialized state */
  32.804 +static void xenfb_frontend_initialized_fb(void *opaque)
  32.805 +{
  32.806 +	struct xenfb_device *dev = (struct xenfb_device *)opaque;
  32.807 +	int ret = xenfb_frontend_initialized(dev);
  32.808 +	if (ret < 0) {
  32.809 +		xenfb_shutdown(dev->xenfb);
  32.810 +		exit(1);
  32.811 +	}
  32.812 +	if (ret)
  32.813 +		return; /* Still waiting */
  32.814 +
  32.815 +
  32.816 +	if (xenfb_read_frontend_fb_config(dev->xenfb)) {
  32.817 +		xenfb_shutdown(dev->xenfb);
  32.818 +	        exit(1);
  32.819 +	}
  32.820 +
  32.821 +        fprintf(stderr, "FB: Waiting for KBD frontend connection\n");
  32.822 +	xenfb_wait_for_frontend(&dev->xenfb->kbd, xenfb_frontend_connected_kbd);
  32.823 +}
  32.824 +
  32.825 +/* Callback invoked while waiting for KBD frontend to change
  32.826 + * to the connected state */
  32.827 +static void xenfb_frontend_connected_kbd(void *opaque)
  32.828 +{
  32.829 +	struct xenfb_device *dev = (struct xenfb_device *)opaque;
  32.830 +	int ret = xenfb_frontend_connected(dev);
  32.831 +	if (ret < 0) {
  32.832 +		xenfb_shutdown(dev->xenfb);
  32.833 +		exit(1);
  32.834 +	}
  32.835 +	if (ret)
  32.836 +		return; /* Still waiting */
  32.837 +
  32.838 +	if (xenfb_read_frontend_kbd_config(dev->xenfb) < 0) {
  32.839 +		xenfb_shutdown(dev->xenfb);
  32.840 +	        exit(1);
  32.841 +	}
  32.842 +
  32.843 +	xenfb_register_console(dev->xenfb);
  32.844 +}
  32.845 +
  32.846 +
  32.847 +/****************************************************************
  32.848 + *
  32.849 + * Helper functions for checking state of frontend/backend devices
  32.850 + *
  32.851 + ****************************************************************/
  32.852 +
  32.853 +/* Helper to determine if a frontend device is in Connected state */
  32.854 +static int xenfb_frontend_connected(struct xenfb_device *dev)
  32.855 +{
  32.856 +	unsigned int state;
  32.857 +	unsigned int dummy;
  32.858 +	char **vec;
  32.859 +	vec = xs_read_watch(dev->xenfb->xsh, &dummy);
  32.860 +	if (!vec)
  32.861 +		return -1;
  32.862 +	free(vec);
  32.863 +
  32.864 +	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
  32.865 +	if (!((1 <<state) & ((1 << XenbusStateUnknown) |
  32.866 +			     (1 << XenbusStateConnected)))) {
  32.867 +		fprintf(stderr, "FB: Carry on waiting\n");
  32.868 +		return 1;
  32.869 +	}
  32.870 +
  32.871 +	/* Don't unwatch frontend - we need to detect shutdown */
  32.872 +	/*xs_unwatch(dev->xenfb->xsh, dev->otherend, "");*/
  32.873 +
  32.874 +	switch (state) {
  32.875 +	case XenbusStateConnected:
  32.876 +		break;
  32.877 +	default:
  32.878 +		return -1;
  32.879 +	}
  32.880 +	return 0;
  32.881 +}
  32.882 +
  32.883 +
  32.884 +/* Helper to determine if a frontend device is in Initialized state */
  32.885 +static int xenfb_frontend_initialized(struct xenfb_device *dev)
  32.886 +{
  32.887 +	unsigned int state;
  32.888 +	unsigned int dummy;
  32.889 +	char **vec;
  32.890 +	vec = xs_read_watch(dev->xenfb->xsh, &dummy);
  32.891 +	if (!vec)
  32.892 +		return -1;
  32.893 +	free(vec);
  32.894 +
  32.895 +	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
  32.896 +
  32.897 +	if (!((1 << state) & ((1 << XenbusStateUnknown)
  32.898 +			      | (1 << XenbusStateInitialised)
  32.899 +#if 1 /* TODO fudging state to permit restarting; to be removed */
  32.900 +			      | (1 << XenbusStateConnected)
  32.901 +#endif
  32.902 +			      ))) {
  32.903 +		fprintf(stderr, "FB: Carry on waiting\n");
  32.904 +		return 1;
  32.905 +	}
  32.906 +
  32.907 +	xs_unwatch(dev->xenfb->xsh, dev->otherend, "");
  32.908 +
  32.909 +	switch (state) {
  32.910 +#if 1
  32.911 +	case XenbusStateConnected:
  32.912 +                printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */
  32.913 +#endif
  32.914 +        case XenbusStateInitialised:
  32.915 +                break;
  32.916 +        default:
  32.917 +                return -1;
  32.918 +        }
  32.919 +
  32.920 +	if (xenfb_bind(dev) < 0)
  32.921 +		return -1;
  32.922 +
  32.923 +	return 0;
  32.924 +}
  32.925 +
  32.926 +/* Helper to determine if a backend device is in Created state */
  32.927 +static int xenfb_backend_created(struct xenfb_device *dev)
  32.928 +{
  32.929 +	unsigned int state;
  32.930 +	unsigned int dummy;
  32.931 +	char **vec;
  32.932 +	vec = xs_read_watch(dev->xenfb->xsh, &dummy);
  32.933 +	if (!vec)
  32.934 +		return -1;
  32.935 +	free(vec);
  32.936 +
  32.937 +	state = xenfb_read_state(dev->xenfb->xsh, dev->nodename);
  32.938 +
  32.939 +	if (!((1 <<state) & ((1 << XenbusStateUnknown)
  32.940 +			     | (1 << XenbusStateInitialising)
  32.941 +			     | (1 << XenbusStateClosed)
  32.942 +#if 1 /* TODO fudging state to permit restarting; to be removed */
  32.943 +			     | (1 << XenbusStateInitWait)
  32.944 +			     | (1 << XenbusStateConnected)
  32.945 +			     | (1 << XenbusStateClosing)
  32.946 +#endif
  32.947 +			     ))) {
  32.948 +		fprintf(stderr, "FB: Carry on waiting\n");
  32.949 +		return 1;
  32.950 +	}
  32.951 +
  32.952 +	xs_unwatch(dev->xenfb->xsh, dev->nodename, "");
  32.953 +
  32.954 +        switch (state) {
  32.955 +#if 1
  32.956 +        case XenbusStateInitWait:
  32.957 +        case XenbusStateConnected:
  32.958 +                printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */
  32.959 +#endif
  32.960 +        case XenbusStateInitialising:
  32.961 +        case XenbusStateClosing:
  32.962 +        case XenbusStateClosed:
  32.963 +                break;
  32.964 +        default:
  32.965 +                fprintf(stderr, "Wrong state %d\n", state);
  32.966 +                return -1;
  32.967 +        }
  32.968 +        xenfb_switch_state(dev, XenbusStateInitWait);
  32.969 +        if (xenfb_hotplug(dev) < 0)
  32.970 +                return -1;
  32.971 +
  32.972 +        return 0;
  32.973 +}
  32.974 +
  32.975 +
  32.976 +/****************************************************************
  32.977 + * 
  32.978 + * QEMU device model integration functions
  32.979 + *
  32.980 + ****************************************************************/
  32.981 +
  32.982 +/* 
  32.983 + * Send a key event from the client to the guest OS
  32.984 + * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
  32.985 + * We have to turn this into a Linux Input layer keycode.
  32.986 + * 
  32.987 + * Extra complexity from the fact that with extended scancodes 
  32.988 + * (like those produced by arrow keys) this method gets called
  32.989 + * twice, but we only want to send a single event. So we have to
  32.990 + * track the '0xe0' scancode state & collapse the extended keys
  32.991 + * as needed.
  32.992 + * 
  32.993 + * Wish we could just send scancodes straight to the guest which
  32.994 + * already has code for dealing with this...
  32.995 + */
  32.996 +static void xenfb_key_event(void *opaque, int scancode)
  32.997 +{
  32.998 +    static int extended = 0;
  32.999 +    int down = 1;
 32.1000 +    if (scancode == 0xe0) {
 32.1001 +        extended = 1;
 32.1002 +        return;
 32.1003 +    } else if (scancode & 0x80) {
 32.1004 +        scancode &= 0x7f;
 32.1005 +        down = 0;
 32.1006 +    }
 32.1007 +    if (extended) {
 32.1008 +        scancode |= 0x80;
 32.1009 +        extended = 0;
 32.1010 +    }
 32.1011 +    xenfb_send_key(opaque, down, scancode2linux[scancode]);
 32.1012 +}
 32.1013 +
 32.1014 +/*
 32.1015 + * Send a mouse event from the client to the guest OS
 32.1016 + * 
 32.1017 + * The QEMU mouse can be in either relative, or absolute mode.
 32.1018 + * Movement is sent separately from button state, which has to
 32.1019 + * be encoded as virtual key events. We also don't actually get
 32.1020 + * given any button up/down events, so have to track changes in
 32.1021 + * the button state.
 32.1022 + */
 32.1023 +static void xenfb_mouse_event(void *opaque,
 32.1024 +			      int dx, int dy, int dz, int button_state)
 32.1025 +{
 32.1026 +    int i;
 32.1027 +    struct xenfb *xenfb = opaque;
 32.1028 +    if (xenfb->abs_pointer_wanted)
 32.1029 +	    xenfb_send_position(xenfb,
 32.1030 +				dx * xenfb->ds->width / 0x7fff,
 32.1031 +				dy * xenfb->ds->height / 0x7fff);
 32.1032 +    else
 32.1033 +	    xenfb_send_motion(xenfb, dx, dy);
 32.1034 +
 32.1035 +    for (i = 0 ; i < 8 ; i++) {
 32.1036 +	    int lastDown = xenfb->button_state & (1 << i);
 32.1037 +	    int down = button_state & (1 << i);
 32.1038 +	    if (down == lastDown)
 32.1039 +		    continue;
 32.1040 +
 32.1041 +	    if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
 32.1042 +		    return;
 32.1043 +    }
 32.1044 +    xenfb->button_state = button_state;
 32.1045 +}
 32.1046 +
 32.1047 +/* A convenient function for munging pixels between different depths */
 32.1048 +#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM)               \
 32.1049 +    for (line = y ; line < h ; line++) {                                \
 32.1050 +        SRC_T *src = (SRC_T *)(xenfb->pixels                            \
 32.1051 +                               + (line * xenfb->row_stride)             \
 32.1052 +                               + (x * xenfb->depth / 8));               \
 32.1053 +        DST_T *dst = (DST_T *)(xenfb->ds->data                                 \
 32.1054 +                               + (line * xenfb->ds->linesize)                  \
 32.1055 +                               + (x * xenfb->ds->depth / 8));                  \
 32.1056 +        int col;                                                        \
 32.1057 +        for (col = x ; col < w ; col++) {                               \
 32.1058 +            *dst = (((*src >> RRS) & RM) << RLS) |                      \
 32.1059 +                (((*src >> GRS) & GM) << GLS) |                         \
 32.1060 +                (((*src >> GRS) & BM) << BLS);                          \
 32.1061 +            src++;                                                      \
 32.1062 +            dst++;                                                      \
 32.1063 +        }                                                               \
 32.1064 +    }
 32.1065 +
 32.1066 +
 32.1067 +/* This copies data from the guest framebuffer region, into QEMU's copy
 32.1068 + * NB. QEMU's copy is stored in the pixel format of a) the local X 
 32.1069 + * server (SDL case) or b) the current VNC client pixel format.
 32.1070 + * When shifting between colour depths we preserve the MSB.
 32.1071 + */
 32.1072 +static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
 32.1073 +{
 32.1074 +    int line;
 32.1075 +
 32.1076 +    if (xenfb->depth == xenfb->ds->depth) { /* Perfect match can use fast path */
 32.1077 +        for (line = y ; line < (y+h) ; line++) {
 32.1078 +            memcpy(xenfb->ds->data + (line * xenfb->ds->linesize) + (x * xenfb->ds->depth / 8),
 32.1079 +                   xenfb->pixels + (line * xenfb->row_stride) + (x * xenfb->depth / 8),
 32.1080 +                   w * xenfb->depth / 8);
 32.1081 +        }
 32.1082 +    } else { /* Mismatch requires slow pixel munging */
 32.1083 +        if (xenfb->depth == 8) {
 32.1084 +            /* 8 bit source == r:3 g:3 b:2 */
 32.1085 +            if (xenfb->ds->depth == 16) {
 32.1086 +                BLT(uint8_t, uint16_t,   5, 2, 0,   11, 5, 0,   7, 7, 3);
 32.1087 +            } else if (xenfb->ds->depth == 32) {
 32.1088 +                BLT(uint8_t, uint32_t,   5, 2, 0,   16, 8, 0,   7, 7, 3);
 32.1089 +            }
 32.1090 +        } else if (xenfb->depth == 16) {
 32.1091 +            /* 16 bit source == r:5 g:6 b:5 */
 32.1092 +            if (xenfb->ds->depth == 8) {
 32.1093 +                BLT(uint16_t, uint8_t,    11, 5, 0,   5, 2, 0,    31, 63, 31);
 32.1094 +            } else if (xenfb->ds->depth == 32) {
 32.1095 +                BLT(uint16_t, uint32_t,   11, 5, 0,   16, 8, 0,   31, 63, 31);
 32.1096 +            }
 32.1097 +        } else if (xenfb->depth == 32) {
 32.1098 +            /* 32 bit source == r:8 g:8 b:8 (padding:8) */
 32.1099 +            if (xenfb->ds->depth == 8) {
 32.1100 +                BLT(uint32_t, uint8_t,    16, 8, 0,   5, 2, 0,    255, 255, 255);
 32.1101 +            } else if (xenfb->ds->depth == 16) {
 32.1102 +                BLT(uint32_t, uint16_t,   16, 8, 0,   11, 5, 0,   255, 255, 255);
 32.1103 +            }
 32.1104 +        }
 32.1105 +    }
 32.1106 +    dpy_update(xenfb->ds, x, y, w, h);
 32.1107 +}
 32.1108 +
 32.1109 +/* QEMU display state changed, so refresh the framebuffer copy */
 32.1110 +/* XXX - can we optimize this, or the next func at all ? */ 
 32.1111 +static void xenfb_update(void *opaque)
 32.1112 +{
 32.1113 +    struct xenfb *xenfb = opaque;
 32.1114 +    xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
 32.1115 +}
 32.1116 +
 32.1117 +/* QEMU display state changed, so refresh the framebuffer copy */
 32.1118 +static void xenfb_invalidate(void *opaque)
 32.1119 +{
 32.1120 +    struct xenfb *xenfb = opaque;
 32.1121 +    xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
 32.1122 +}
 32.1123 +
 32.1124 +/* Screen dump is not used in Xen, so no need to impl this....yet */
 32.1125 +static void xenfb_screen_dump(void *opaque, const char *name) { }
 32.1126 +
 32.1127 +
 32.1128 +/* Register a QEMU graphical console, and key/mouse handler,
 32.1129 + * connecting up their events to the frontend */
 32.1130 +static int xenfb_register_console(struct xenfb *xenfb) {
 32.1131 +	/* Register our keyboard & mouse handlers */
 32.1132 +	qemu_add_kbd_event_handler(xenfb_key_event, xenfb);
 32.1133 +	qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb,
 32.1134 +  				     xenfb->abs_pointer_wanted,
 32.1135 +  				     "Xen PVFB Mouse");
 32.1136 +  
 32.1137 +  	/* Tell QEMU to allocate a graphical console */
 32.1138 +	graphic_console_init(xenfb->ds,
 32.1139 +			     xenfb_update,
 32.1140 +			     xenfb_invalidate,
 32.1141 +			     xenfb_screen_dump,
 32.1142 +			     xenfb);
 32.1143 +	dpy_resize(xenfb->ds, xenfb->width, xenfb->height);
 32.1144 +
 32.1145 +	if (qemu_set_fd_handler2(xenfb->evt_xch, NULL, xenfb_dispatch_channel, NULL, xenfb) < 0)
 32.1146 +	        return -1;
 32.1147 +	if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL, xenfb_dispatch_store, NULL, xenfb) < 0)
 32.1148 +		return -1;
 32.1149 +
 32.1150 +        fprintf(stderr, "Xen Framebuffer registered\n");
 32.1151 +        return 0;
 32.1152 +}
 32.1153 +
 32.1154 +/*
 32.1155 + * Local variables:
 32.1156 + *  c-indent-level: 8
 32.1157 + *  c-basic-offset: 8
 32.1158 + *  tab-width: 8
 32.1159 + * End:
 32.1160 + */
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/tools/ioemu/hw/xenfb.h	Tue Oct 30 15:34:44 2007 -0600
    33.3 @@ -0,0 +1,13 @@
    33.4 +#ifndef _XENFB_H_
    33.5 +#define _XENFB_H_
    33.6 +
    33.7 +#include "vl.h"
    33.8 +#include <stdbool.h>
    33.9 +#include <sys/types.h>
   33.10 +
   33.11 +struct xenfb;
   33.12 +
   33.13 +struct xenfb *xenfb_new(int domid, DisplayState *ds);
   33.14 +void xenfb_shutdown(struct xenfb *xenfb);
   33.15 +
   33.16 +#endif
    34.1 --- a/tools/ioemu/monitor.c	Tue Oct 30 11:33:55 2007 -0600
    34.2 +++ b/tools/ioemu/monitor.c	Tue Oct 30 15:34:44 2007 -0600
    34.3 @@ -374,7 +374,7 @@ void do_eject(int force, const char *fil
    34.4      eject_device(bs, force);
    34.5  }
    34.6  
    34.7 -void do_change(const char *device, const char *filename)
    34.8 +static void do_change_block(const char *device, const char *filename)
    34.9  {
   34.10      BlockDriverState *bs;
   34.11      int i;
   34.12 @@ -399,6 +399,30 @@ void do_change(const char *device, const
   34.13      }
   34.14  }
   34.15  
   34.16 +static void do_change_vnc(const char *target)
   34.17 +{
   34.18 +    if (strcmp(target, "passwd") == 0 ||
   34.19 +	strcmp(target, "password") == 0) {
   34.20 +	char password[9];
   34.21 +	monitor_readline("Password: ", 1, password, sizeof(password)-1);
   34.22 +	password[sizeof(password)-1] = '\0';
   34.23 +	if (vnc_display_password(NULL, password) < 0)
   34.24 +	    term_printf("could not set VNC server password\n");
   34.25 +    } else {
   34.26 +	if (vnc_display_open(NULL, target, 0) < 0)
   34.27 +	    term_printf("could not start VNC server on %s\n", target);
   34.28 +    }
   34.29 +}
   34.30 +
   34.31 +void do_change(const char *device, const char *target)
   34.32 +{
   34.33 +    if (strcmp(device, "vnc") == 0) {
   34.34 +	do_change_vnc(target);
   34.35 +    } else {
   34.36 +	do_change_block(device, target);
   34.37 +    }
   34.38 +}
   34.39 +
   34.40  static void do_screen_dump(const char *filename)
   34.41  {
   34.42      vga_hw_screen_dump(filename);
    35.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Tue Oct 30 11:33:55 2007 -0600
    35.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Tue Oct 30 15:34:44 2007 -0600
    35.3 @@ -478,6 +478,7 @@ void cpu_ioreq_timeoffset(CPUState *env,
    35.4  
    35.5      time_offset += (ulong)req->data;
    35.6  
    35.7 +    fprintf(logfile, "Time offset set %ld, added offset %ld\n", time_offset, req->data);
    35.8      sprintf(b, "%ld", time_offset);
    35.9      xenstore_vm_write(domid, "rtc/timeoffset", b);
   35.10  }
   35.11 @@ -538,20 +539,39 @@ void __handle_ioreq(CPUState *env, ioreq
   35.12  
   35.13  void __handle_buffered_iopage(CPUState *env)
   35.14  {
   35.15 -    ioreq_t *req = NULL;
   35.16 +    buf_ioreq_t *buf_req = NULL;
   35.17 +    ioreq_t req;
   35.18 +    int qw = 0;
   35.19  
   35.20      if (!buffered_io_page)
   35.21          return;
   35.22  
   35.23      while (buffered_io_page->read_pointer !=
   35.24             buffered_io_page->write_pointer) {
   35.25 -        req = &buffered_io_page->ioreq[buffered_io_page->read_pointer %
   35.26 +        memset(&req, 0, sizeof(req));
   35.27 +        buf_req = &buffered_io_page->buf_ioreq[buffered_io_page->read_pointer %
   35.28  				       IOREQ_BUFFER_SLOT_NUM];
   35.29 +        req.size = 1UL << buf_req->size;
   35.30 +        req.count = 1;
   35.31 +        req.data = buf_req->data;
   35.32 +        req.state = STATE_IOREQ_READY;
   35.33 +        req.dir  = buf_req->dir;
   35.34 +        req.type = buf_req->type;
   35.35 +        qw = req.size == 8;
   35.36 +        if (qw) {
   35.37 +            req.data |= ((uint64_t)buf_req->addr) << 16;
   35.38 +            buf_req = &buffered_io_page->buf_ioreq[(buffered_io_page->read_pointer+1) %
   35.39 +                                               IOREQ_BUFFER_SLOT_NUM];
   35.40 +            req.data |= ((uint64_t)buf_req->data) << 32;
   35.41 +            req.data |= ((uint64_t)buf_req->addr) << 48;
   35.42 +        }
   35.43 +        else
   35.44 +            req.addr = buf_req->addr;
   35.45  
   35.46 -        __handle_ioreq(env, req);
   35.47 +        __handle_ioreq(env, &req);
   35.48  
   35.49          mb();
   35.50 -        buffered_io_page->read_pointer++;
   35.51 +        buffered_io_page->read_pointer += qw ? 2 : 1;
   35.52      }
   35.53  }
   35.54  
   35.55 @@ -616,7 +636,7 @@ int main_loop(void)
   35.56      extern int shutdown_requested;
   35.57      extern int suspend_requested;
   35.58      CPUState *env = cpu_single_env;
   35.59 -    int evtchn_fd = xc_evtchn_fd(xce_handle);
   35.60 +    int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
   35.61      char qemu_file[PATH_MAX];
   35.62      fd_set fds;
   35.63  
   35.64 @@ -624,7 +644,8 @@ int main_loop(void)
   35.65  				       cpu_single_env);
   35.66      qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock));
   35.67  
   35.68 -    qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
   35.69 +    if (evtchn_fd != -1)
   35.70 +        qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
   35.71  
   35.72      xenstore_record_dm_state("running");
   35.73      while (1) {
    36.1 --- a/tools/ioemu/vl.c	Tue Oct 30 11:33:55 2007 -0600
    36.2 +++ b/tools/ioemu/vl.c	Tue Oct 30 15:34:44 2007 -0600
    36.3 @@ -96,7 +96,6 @@
    36.4  
    36.5  #include "exec-all.h"
    36.6  
    36.7 -#include <xen/hvm/params.h>
    36.8  #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
    36.9  #ifdef _BSD
   36.10  #define DEFAULT_BRIDGE "bridge0"
   36.11 @@ -194,12 +193,9 @@ extern int vcpus;
   36.12  
   36.13  int xc_handle;
   36.14  
   36.15 -char domain_name[64] = "Xen-HVM-no-name";
   36.16 +char domain_name[64] = "Xen-no-name";
   36.17  extern int domid;
   36.18  
   36.19 -char vncpasswd[64];
   36.20 -unsigned char challenge[AUTHCHALLENGESIZE];
   36.21 -
   36.22  /***********************************************************/
   36.23  /* x86 ISA bus support */
   36.24  
   36.25 @@ -6204,12 +6200,10 @@ void main_loop_wait(int timeout)
   36.26          IOHandlerRecord **pioh;
   36.27  
   36.28          for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
   36.29 -            if (ioh->deleted)
   36.30 -                continue;
   36.31 -            if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
   36.32 +            if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
   36.33                  ioh->fd_read(ioh->opaque);
   36.34              }
   36.35 -            if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
   36.36 +            if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
   36.37                  ioh->fd_write(ioh->opaque);
   36.38              }
   36.39          }
   36.40 @@ -6696,8 +6690,13 @@ static void read_passwords(void)
   36.41  void register_machines(void)
   36.42  {
   36.43  #if defined(TARGET_I386)
   36.44 +#ifndef CONFIG_DM
   36.45      qemu_register_machine(&pc_machine);
   36.46      qemu_register_machine(&isapc_machine);
   36.47 +#else
   36.48 +    qemu_register_machine(&xenfv_machine);
   36.49 +    qemu_register_machine(&xenpv_machine);
   36.50 +#endif
   36.51  #elif defined(TARGET_PPC)
   36.52      qemu_register_machine(&heathrow_machine);
   36.53      qemu_register_machine(&core99_machine);
   36.54 @@ -6905,156 +6904,6 @@ int set_mm_mapping(int xc_handle, uint32
   36.55      return 0;
   36.56  }
   36.57  
   36.58 -#if defined(MAPCACHE)
   36.59 -
   36.60 -#if defined(__i386__) 
   36.61 -#define MAX_MCACHE_SIZE    0x40000000 /* 1GB max for x86 */
   36.62 -#define MCACHE_BUCKET_SHIFT 16
   36.63 -#elif defined(__x86_64__)
   36.64 -#define MAX_MCACHE_SIZE    0x1000000000 /* 64GB max for x86_64 */
   36.65 -#define MCACHE_BUCKET_SHIFT 20
   36.66 -#endif
   36.67 -
   36.68 -#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
   36.69 -
   36.70 -#define BITS_PER_LONG (sizeof(long)*8)
   36.71 -#define BITS_TO_LONGS(bits) \
   36.72 -    (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
   36.73 -#define DECLARE_BITMAP(name,bits) \
   36.74 -    unsigned long name[BITS_TO_LONGS(bits)]
   36.75 -#define test_bit(bit,map) \
   36.76 -    (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG))))
   36.77 -
   36.78 -struct map_cache {
   36.79 -    unsigned long paddr_index;
   36.80 -    uint8_t      *vaddr_base;
   36.81 -    DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT);
   36.82 -};
   36.83 -
   36.84 -static struct map_cache *mapcache_entry;
   36.85 -static unsigned long nr_buckets;
   36.86 -
   36.87 -/* For most cases (>99.9%), the page address is the same. */
   36.88 -static unsigned long last_address_index = ~0UL;
   36.89 -static uint8_t      *last_address_vaddr;
   36.90 -
   36.91 -static int qemu_map_cache_init(void)
   36.92 -{
   36.93 -    unsigned long size;
   36.94 -
   36.95 -    nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
   36.96 -                   (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
   36.97 -                  (MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
   36.98 -
   36.99 -    /*
  36.100 -     * Use mmap() directly: lets us allocate a big hash table with no up-front
  36.101 -     * cost in storage space. The OS will allocate memory only for the buckets
  36.102 -     * that we actually use. All others will contain all zeroes.
  36.103 -     */
  36.104 -    size = nr_buckets * sizeof(struct map_cache);
  36.105 -    size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
  36.106 -    fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n", nr_buckets, size);
  36.107 -    mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
  36.108 -                          MAP_SHARED|MAP_ANON, -1, 0);
  36.109 -    if (mapcache_entry == MAP_FAILED) {
  36.110 -        errno = ENOMEM;
  36.111 -        return -1;
  36.112 -    }
  36.113 -
  36.114 -    return 0;
  36.115 -}
  36.116 -
  36.117 -static void qemu_remap_bucket(struct map_cache *entry,
  36.118 -                              unsigned long address_index)
  36.119 -{
  36.120 -    uint8_t *vaddr_base;
  36.121 -    unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT];
  36.122 -    unsigned int i, j;
  36.123 -
  36.124 -    if (entry->vaddr_base != NULL) {
  36.125 -        errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
  36.126 -        if (errno) {
  36.127 -            fprintf(logfile, "unmap fails %d\n", errno);
  36.128 -            exit(-1);
  36.129 -        }
  36.130 -    }
  36.131 -
  36.132 -    for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++)
  36.133 -        pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i;
  36.134 -
  36.135 -    vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE,
  36.136 -                                      pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT);
  36.137 -    if (vaddr_base == NULL) {
  36.138 -        fprintf(logfile, "xc_map_foreign_batch error %d\n", errno);
  36.139 -        exit(-1);
  36.140 -    }
  36.141 -
  36.142 -    entry->vaddr_base  = vaddr_base;
  36.143 -    entry->paddr_index = address_index;
  36.144 -
  36.145 -    for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) {
  36.146 -        unsigned long word = 0;
  36.147 -        j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ?
  36.148 -            (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;
  36.149 -        while (j > 0)
  36.150 -            word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf);
  36.151 -        entry->valid_mapping[i / BITS_PER_LONG] = word;
  36.152 -    }
  36.153 -}
  36.154 -
  36.155 -uint8_t *qemu_map_cache(target_phys_addr_t phys_addr)
  36.156 -{
  36.157 -    struct map_cache *entry;
  36.158 -    unsigned long address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
  36.159 -    unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1);
  36.160 -
  36.161 -    if (address_index == last_address_index)
  36.162 -        return last_address_vaddr + address_offset;
  36.163 -
  36.164 -    entry = &mapcache_entry[address_index % nr_buckets];
  36.165 -
  36.166 -    if (entry->vaddr_base == NULL || entry->paddr_index != address_index ||
  36.167 -        !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
  36.168 -        qemu_remap_bucket(entry, address_index);
  36.169 -
  36.170 -    if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
  36.171 -        return NULL;
  36.172 -
  36.173 -    last_address_index = address_index;
  36.174 -    last_address_vaddr = entry->vaddr_base;
  36.175 -
  36.176 -    return last_address_vaddr + address_offset;
  36.177 -}
  36.178 -
  36.179 -void qemu_invalidate_map_cache(void)
  36.180 -{
  36.181 -    unsigned long i;
  36.182 -
  36.183 -    mapcache_lock();
  36.184 -
  36.185 -    for (i = 0; i < nr_buckets; i++) {
  36.186 -        struct map_cache *entry = &mapcache_entry[i];
  36.187 -
  36.188 -        if (entry->vaddr_base == NULL)
  36.189 -            continue;
  36.190 -
  36.191 -        errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
  36.192 -        if (errno) {
  36.193 -            fprintf(logfile, "unmap fails %d\n", errno);
  36.194 -            exit(-1);
  36.195 -        }
  36.196 -
  36.197 -        entry->paddr_index = 0;
  36.198 -        entry->vaddr_base  = NULL;
  36.199 -    }
  36.200 -
  36.201 -    last_address_index =  ~0UL;
  36.202 -    last_address_vaddr = NULL;
  36.203 -
  36.204 -    mapcache_unlock();
  36.205 -}
  36.206 -
  36.207 -#endif /* defined(MAPCACHE) */
  36.208  
  36.209  int main(int argc, char **argv)
  36.210  {
  36.211 @@ -7089,15 +6938,7 @@ int main(int argc, char **argv)
  36.212      char usb_devices[MAX_USB_CMDLINE][128];
  36.213      int usb_devices_index;
  36.214      int fds[2];
  36.215 -    unsigned long ioreq_pfn;
  36.216 -    extern void *shared_page;
  36.217 -    extern void *buffered_io_page;
  36.218      struct rlimit rl;
  36.219 -#ifdef __ia64__
  36.220 -    unsigned long nr_pages;
  36.221 -    xen_pfn_t *page_array;
  36.222 -    extern void *buffered_pio_page;
  36.223 -#endif
  36.224      sigset_t set;
  36.225      char qemu_dm_logfilename[128];
  36.226      const char *direct_pci = NULL;
  36.227 @@ -7193,7 +7034,6 @@ int main(int argc, char **argv)
  36.228      vncunused = 0;
  36.229      kernel_filename = NULL;
  36.230      kernel_cmdline = "";
  36.231 -    *vncpasswd = '\0';
  36.232  #ifndef CONFIG_DM
  36.233  #ifdef TARGET_PPC
  36.234      cdrom_index = 1;
  36.235 @@ -7601,7 +7441,7 @@ int main(int argc, char **argv)
  36.236                  break;
  36.237              case QEMU_OPTION_domainname:
  36.238                  snprintf(domain_name, sizeof(domain_name),
  36.239 -                         "Xen-HVM-%s", optarg);
  36.240 +                         "Xen-%s", optarg);
  36.241                  break;
  36.242              case QEMU_OPTION_d:
  36.243                  domid = atoi(optarg);
  36.244 @@ -7681,6 +7521,7 @@ int main(int argc, char **argv)
  36.245  
  36.246  #ifdef CONFIG_DM
  36.247      bdrv_init();
  36.248 +    xc_handle = xc_interface_open();
  36.249      xenstore_parse_domain_config(domid);
  36.250  #endif /* CONFIG_DM */
  36.251  
  36.252 @@ -7774,83 +7615,6 @@ int main(int argc, char **argv)
  36.253  	}
  36.254  	phys_ram_size += ret;
  36.255      }
  36.256 -#endif /* !CONFIG_DM */
  36.257 -
  36.258 -#ifdef CONFIG_DM
  36.259 -
  36.260 -    xc_handle = xc_interface_open();
  36.261 -
  36.262 -#if defined(__i386__) || defined(__x86_64__)
  36.263 -
  36.264 -    if (qemu_map_cache_init()) {
  36.265 -        fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno);
  36.266 -        exit(-1);
  36.267 -    }
  36.268 -
  36.269 -    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
  36.270 -    fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn);
  36.271 -    shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  36.272 -                                       PROT_READ|PROT_WRITE, ioreq_pfn);
  36.273 -    if (shared_page == NULL) {
  36.274 -        fprintf(logfile, "map shared IO page returned error %d\n", errno);
  36.275 -        exit(-1);
  36.276 -    }
  36.277 -
  36.278 -    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
  36.279 -    fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
  36.280 -    buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  36.281 -                                            PROT_READ|PROT_WRITE, ioreq_pfn);
  36.282 -    if (buffered_io_page == NULL) {
  36.283 -        fprintf(logfile, "map buffered IO page returned error %d\n", errno);
  36.284 -        exit(-1);
  36.285 -    }
  36.286 -
  36.287 -#elif defined(__ia64__)
  36.288 -
  36.289 -    nr_pages = ram_size/PAGE_SIZE;
  36.290 -
  36.291 -    page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t));
  36.292 -    if (page_array == NULL) {
  36.293 -        fprintf(logfile, "malloc returned error %d\n", errno);
  36.294 -        exit(-1);
  36.295 -    }
  36.296 -
  36.297 -    shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  36.298 -                                       PROT_READ|PROT_WRITE,
  36.299 -                                       IO_PAGE_START >> PAGE_SHIFT);
  36.300 -
  36.301 -    buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  36.302 -                                       PROT_READ|PROT_WRITE,
  36.303 -                                       BUFFER_IO_PAGE_START >> PAGE_SHIFT);
  36.304 -
  36.305 -    buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  36.306 -                                       PROT_READ|PROT_WRITE,
  36.307 -                                       BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
  36.308 -
  36.309 -    for (i = 0; i < nr_pages; i++)
  36.310 -        page_array[i] = i;
  36.311 -	
  36.312 -    /* VTI will not use memory between 3G~4G, so we just pass a legal pfn
  36.313 -       to make QEMU map continuous virtual memory space */
  36.314 -    if (ram_size > MMIO_START) {	
  36.315 -        for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++)
  36.316 -            page_array[(MMIO_START >> PAGE_SHIFT) + i] =
  36.317 -                (STORE_PAGE_START >> PAGE_SHIFT); 
  36.318 -    }
  36.319 -
  36.320 -    phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
  36.321 -                                         PROT_READ|PROT_WRITE,
  36.322 -                                         page_array, nr_pages);
  36.323 -    if (phys_ram_base == 0) {
  36.324 -        fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
  36.325 -        exit(-1);
  36.326 -    }
  36.327 -    free(page_array);
  36.328 -#endif
  36.329 -
  36.330 -    timeoffset_get();
  36.331 -
  36.332 -#else  /* !CONFIG_DM */
  36.333  
  36.334      phys_ram_base = qemu_vmalloc(phys_ram_size);
  36.335      if (!phys_ram_base) {
  36.336 @@ -7858,9 +7622,6 @@ int main(int argc, char **argv)
  36.337          exit(1);
  36.338      }
  36.339  
  36.340 -#endif /* !CONFIG_DM */
  36.341 -
  36.342 -#ifndef CONFIG_DM
  36.343      /* we always create the cdrom drive, even if no disk is there */
  36.344      bdrv_init();
  36.345      if (cdrom_index >= 0) {
  36.346 @@ -7917,17 +7678,19 @@ int main(int argc, char **argv)
  36.347  
  36.348      init_ioports();
  36.349  
  36.350 -    /* read vncpasswd from xenstore */
  36.351 -    if (0 > xenstore_read_vncpasswd(domid))
  36.352 -        exit(1);
  36.353 -
  36.354      /* terminal init */
  36.355      if (nographic) {
  36.356          dumb_display_init(ds);
  36.357      } else if (vnc_display != NULL || vncunused != 0) {
  36.358  	int vnc_display_port;
  36.359 -	vnc_display_port = vnc_display_init(ds, vnc_display, vncunused);
  36.360 -	if (vncviewer)
  36.361 +	char password[20];
  36.362 +	vnc_display_init(ds);
  36.363 +	if (xenstore_read_vncpasswd(domid, password, sizeof(password)) < 0)
  36.364 +	    exit(0);
  36.365 +	vnc_display_password(ds, password);
  36.366 +	if ((vnc_display_port = vnc_display_open(ds, vnc_display, vncunused)) < 0) 
  36.367 +	    exit (0);
  36.368 + 	if (vncviewer)
  36.369  	    vnc_start_viewer(vnc_display_port);
  36.370  	xenstore_write_vncport(vnc_display_port);
  36.371      } else {
    37.1 --- a/tools/ioemu/vl.h	Tue Oct 30 11:33:55 2007 -0600
    37.2 +++ b/tools/ioemu/vl.h	Tue Oct 30 15:34:44 2007 -0600
    37.3 @@ -943,7 +943,10 @@ void sdl_display_init(DisplayState *ds, 
    37.4  void cocoa_display_init(DisplayState *ds, int full_screen);
    37.5  
    37.6  /* vnc.c */
    37.7 -int vnc_display_init(DisplayState *ds, const char *display, int find_unused);
    37.8 +void vnc_display_init(DisplayState *ds);
    37.9 +void vnc_display_close(DisplayState *ds);
   37.10 +int vnc_display_open(DisplayState *ds, const char * display, int find_unused);
   37.11 +int vnc_display_password(DisplayState *ds, const char *password);
   37.12  void do_info_vnc(void);
   37.13  int vnc_start_viewer(int port);
   37.14  
   37.15 @@ -1108,6 +1111,10 @@ extern void pci_piix4_acpi_init(PCIBus *
   37.16  /* pc.c */
   37.17  extern QEMUMachine pc_machine;
   37.18  extern QEMUMachine isapc_machine;
   37.19 +#ifdef CONFIG_DM
   37.20 +extern QEMUMachine xenfv_machine;
   37.21 +extern QEMUMachine xenpv_machine;
   37.22 +#endif
   37.23  extern int fd_bootchk;
   37.24  
   37.25  void ioport_set_a20(int enable);
   37.26 @@ -1449,7 +1456,7 @@ void xenstore_process_event(void *opaque
   37.27  void xenstore_record_dm_state(char *state);
   37.28  void xenstore_check_new_media_present(int timeout);
   37.29  void xenstore_write_vncport(int vnc_display);
   37.30 -int xenstore_read_vncpasswd(int domid);
   37.31 +int xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen);
   37.32  
   37.33  int xenstore_domain_has_devtype(struct xs_handle *handle,
   37.34                                  const char *devtype);
   37.35 @@ -1486,9 +1493,6 @@ extern char domain_name[];
   37.36  
   37.37  void destroy_hvm_domain(void);
   37.38  
   37.39 -/* VNC Authentication */
   37.40 -#define AUTHCHALLENGESIZE 16
   37.41 -
   37.42  #ifdef __ia64__
   37.43  static inline void xc_domain_shutdown_hook(int xc_handle, uint32_t domid)
   37.44  {
    38.1 --- a/tools/ioemu/vnc.c	Tue Oct 30 11:33:55 2007 -0600
    38.2 +++ b/tools/ioemu/vnc.c	Tue Oct 30 15:34:44 2007 -0600
    38.3 @@ -49,6 +49,27 @@
    38.4  #include "keymaps.c"
    38.5  #include "d3des.h"
    38.6  
    38.7 +#if CONFIG_VNC_TLS
    38.8 +#include <gnutls/gnutls.h>
    38.9 +#include <gnutls/x509.h>
   38.10 +#endif /* CONFIG_VNC_TLS */
   38.11 +
   38.12 +// #define _VNC_DEBUG 1
   38.13 +
   38.14 +#if _VNC_DEBUG
   38.15 +#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
   38.16 +
   38.17 +#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
   38.18 +/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
   38.19 +static void vnc_debug_gnutls_log(int level, const char* str) {
   38.20 +    VNC_DEBUG("%d %s", level, str);
   38.21 +}
   38.22 +#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
   38.23 +#else
   38.24 +#define VNC_DEBUG(fmt, ...) do { } while (0)
   38.25 +#endif
   38.26 +
   38.27 +
   38.28  typedef struct Buffer
   38.29  {
   38.30      size_t capacity;
   38.31 @@ -74,6 +95,45 @@ typedef void VncSendHextileTile(VncState
   38.32  #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
   38.33  #endif
   38.34  
   38.35 +#define VNC_AUTH_CHALLENGE_SIZE 16
   38.36 +
   38.37 +enum {
   38.38 +    VNC_AUTH_INVALID = 0,
   38.39 +    VNC_AUTH_NONE = 1,
   38.40 +    VNC_AUTH_VNC = 2,
   38.41 +    VNC_AUTH_RA2 = 5,
   38.42 +    VNC_AUTH_RA2NE = 6,
   38.43 +    VNC_AUTH_TIGHT = 16,
   38.44 +    VNC_AUTH_ULTRA = 17,
   38.45 +    VNC_AUTH_TLS = 18,
   38.46 +    VNC_AUTH_VENCRYPT = 19
   38.47 +};
   38.48 +
   38.49 +#if CONFIG_VNC_TLS
   38.50 +enum {
   38.51 +    VNC_WIREMODE_CLEAR,
   38.52 +    VNC_WIREMODE_TLS,
   38.53 +};
   38.54 +
   38.55 +enum {
   38.56 +    VNC_AUTH_VENCRYPT_PLAIN = 256,
   38.57 +    VNC_AUTH_VENCRYPT_TLSNONE = 257,
   38.58 +    VNC_AUTH_VENCRYPT_TLSVNC = 258,
   38.59 +    VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
   38.60 +    VNC_AUTH_VENCRYPT_X509NONE = 260,
   38.61 +    VNC_AUTH_VENCRYPT_X509VNC = 261,
   38.62 +    VNC_AUTH_VENCRYPT_X509PLAIN = 262,
   38.63 +};
   38.64 +
   38.65 +#if CONFIG_VNC_TLS
   38.66 +#define X509_CA_CERT_FILE "ca-cert.pem"
   38.67 +#define X509_CA_CRL_FILE "ca-crl.pem"
   38.68 +#define X509_SERVER_KEY_FILE "server-key.pem"
   38.69 +#define X509_SERVER_CERT_FILE "server-cert.pem"
   38.70 +#endif
   38.71 +
   38.72 +#endif /* CONFIG_VNC_TLS */
   38.73 +
   38.74  struct VncState
   38.75  {
   38.76      QEMUTimer *timer;
   38.77 @@ -98,7 +158,27 @@ struct VncState
   38.78      int last_x;
   38.79      int last_y;
   38.80  
   38.81 -    const char *display;
   38.82 +    int major;
   38.83 +    int minor;
   38.84 +
   38.85 +    char *display;
   38.86 +    char *password;
   38.87 +    int auth;
   38.88 +#if CONFIG_VNC_TLS
   38.89 +    int subauth;
   38.90 +    int x509verify;
   38.91 +
   38.92 +    char *x509cacert;
   38.93 +    char *x509cacrl;
   38.94 +    char *x509cert;
   38.95 +    char *x509key;
   38.96 +#endif
   38.97 +    char challenge[VNC_AUTH_CHALLENGE_SIZE];
   38.98 +
   38.99 +#if CONFIG_VNC_TLS
  38.100 +    int wiremode;
  38.101 +    gnutls_session_t tls_session;
  38.102 +#endif
  38.103  
  38.104      Buffer output;
  38.105      Buffer input;
  38.106 @@ -164,9 +244,6 @@ static void _vnc_update_client(void *opa
  38.107  static void vnc_update_client(void *opaque);
  38.108  static void vnc_client_read(void *opaque);
  38.109  static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
  38.110 -static int make_challenge(unsigned char *random, int size);
  38.111 -static void set_seed(unsigned int *seedp);
  38.112 -static void get_random(int len, unsigned char *buf);
  38.113  
  38.114  #if 0
  38.115  static inline void vnc_set_bit(uint32_t *d, int k)
  38.116 @@ -702,11 +779,19 @@ static int vnc_client_io_error(VncState 
  38.117  	if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
  38.118  	    return 0;
  38.119  
  38.120 +	VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0);
  38.121  	qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
  38.122  	closesocket(vs->csock);
  38.123  	vs->csock = -1;
  38.124  	buffer_reset(&vs->input);
  38.125  	buffer_reset(&vs->output);
  38.126 +#if CONFIG_VNC_TLS
  38.127 +	if (vs->tls_session) {
  38.128 +	    gnutls_deinit(vs->tls_session);
  38.129 +	    vs->tls_session = NULL;
  38.130 +	}
  38.131 +	vs->wiremode = VNC_WIREMODE_CLEAR;
  38.132 +#endif /* CONFIG_VNC_TLS */
  38.133  	return 0;
  38.134      }
  38.135      return ret;
  38.136 @@ -722,7 +807,19 @@ static void vnc_client_write(void *opaqu
  38.137      long ret;
  38.138      VncState *vs = opaque;
  38.139  
  38.140 -    ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
  38.141 +#if CONFIG_VNC_TLS
  38.142 +    if (vs->tls_session) {
  38.143 +	ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset);
  38.144 +	if (ret < 0) {
  38.145 +	    if (ret == GNUTLS_E_AGAIN)
  38.146 +		errno = EAGAIN;
  38.147 +	    else
  38.148 +		errno = EIO;
  38.149 +	    ret = -1;
  38.150 +	}
  38.151 +    } else
  38.152 +#endif /* CONFIG_VNC_TLS */
  38.153 +	ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
  38.154      ret = vnc_client_io_error(vs, ret, socket_error());
  38.155      if (!ret)
  38.156  	return;
  38.157 @@ -748,7 +845,19 @@ static void vnc_client_read(void *opaque
  38.158  
  38.159      buffer_reserve(&vs->input, 4096);
  38.160  
  38.161 -    ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
  38.162 +#if CONFIG_VNC_TLS
  38.163 +    if (vs->tls_session) {
  38.164 +	ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
  38.165 +	if (ret < 0) {
  38.166 +	    if (ret == GNUTLS_E_AGAIN)
  38.167 +		errno = EAGAIN;
  38.168 +	    else
  38.169 +		errno = EIO;
  38.170 +	    ret = -1;
  38.171 +	}
  38.172 +    } else
  38.173 +#endif /* CONFIG_VNC_TLS */
  38.174 +	ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
  38.175      ret = vnc_client_io_error(vs, ret, socket_error());
  38.176      if (!ret)
  38.177  	return;
  38.178 @@ -845,6 +954,41 @@ static uint32_t read_u32(uint8_t *data, 
  38.179  	    (data[offset + 2] << 8) | data[offset + 3]);
  38.180  }
  38.181  
  38.182 +#if CONFIG_VNC_TLS
  38.183 +ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
  38.184 +		     const void *data,
  38.185 +		     size_t len) {
  38.186 +    struct VncState *vs = (struct VncState *)transport;
  38.187 +    int ret;
  38.188 +
  38.189 + retry:
  38.190 +    ret = send(vs->csock, data, len, 0);
  38.191 +    if (ret < 0) {
  38.192 +	if (errno == EINTR)
  38.193 +	    goto retry;
  38.194 +	return -1;
  38.195 +    }
  38.196 +    return ret;
  38.197 +}
  38.198 +
  38.199 +
  38.200 +ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
  38.201 +		     void *data,
  38.202 +		     size_t len) {
  38.203 +    struct VncState *vs = (struct VncState *)transport;
  38.204 +    int ret;
  38.205 +
  38.206 + retry:
  38.207 +    ret = recv(vs->csock, data, len, 0);
  38.208 +    if (ret < 0) {
  38.209 +	if (errno == EINTR)
  38.210 +	    goto retry;
  38.211 +	return -1;
  38.212 +    }
  38.213 +    return ret;
  38.214 +}
  38.215 +#endif /* CONFIG_VNC_TLS */
  38.216 +
  38.217  static void client_cut_text(VncState *vs, size_t len, char *text)
  38.218  {
  38.219  }
  38.220 @@ -1387,91 +1531,591 @@ static int protocol_client_init(VncState
  38.221      return 0;
  38.222  }
  38.223  
  38.224 -static int protocol_response(VncState *vs, uint8_t *client_response, size_t len)
  38.225 +
  38.226 +static void make_challenge(VncState *vs)
  38.227  {
  38.228 -    extern char vncpasswd[64];
  38.229 -    extern unsigned char challenge[AUTHCHALLENGESIZE];
  38.230 -    unsigned char cryptchallenge[AUTHCHALLENGESIZE];
  38.231 -    unsigned char key[8];
  38.232 -    int passwdlen, i, j;
  38.233 +    int i;
  38.234 +
  38.235 +    srand(time(NULL)+getpid()+getpid()*987654+rand());
  38.236  
  38.237 -    memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE);
  38.238 +    for (i = 0 ; i < sizeof(vs->challenge) ; i++)
  38.239 +        vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
  38.240 +}
  38.241  
  38.242 -    /* Calculate the sent challenge */
  38.243 -    passwdlen = strlen(vncpasswd);
  38.244 -    for (i=0; i<8; i++)
  38.245 -	key[i] = i<passwdlen ? vncpasswd[i] : 0;
  38.246 -    deskey(key, EN0);
  38.247 -    for (j = 0; j < AUTHCHALLENGESIZE; j += 8)
  38.248 -	des(cryptchallenge+j, cryptchallenge+j);
  38.249 +static int protocol_client_auth_vnc(VncState *vs, char *data, size_t len)
  38.250 +{
  38.251 +    char response[VNC_AUTH_CHALLENGE_SIZE];
  38.252 +    int i, j, pwlen;
  38.253 +    char key[8];
  38.254  
  38.255 -    /* Check the actual response */
  38.256 -    if (memcmp(cryptchallenge, client_response, AUTHCHALLENGESIZE) != 0) {
  38.257 -	/* password error */
  38.258 -	vnc_write_u32(vs, 1);
  38.259 -	vnc_write_u32(vs, 22);
  38.260 -	vnc_write(vs, "Authentication failure", 22);
  38.261 +    if (!vs->password || !vs->password[0]) {
  38.262 +	VNC_DEBUG("No password configured on server");
  38.263 +	vnc_write_u32(vs, 1); /* Reject auth */
  38.264 +	if (vs->minor >= 8) {
  38.265 +	    static const char err[] = "Authentication failed";
  38.266 +	    vnc_write_u32(vs, sizeof(err));
  38.267 +	    vnc_write(vs, err, sizeof(err));
  38.268 +	}
  38.269  	vnc_flush(vs);
  38.270 -	fprintf(stderr, "VNC Password error.\n");
  38.271  	vnc_client_error(vs);
  38.272  	return 0;
  38.273      }
  38.274  
  38.275 -    vnc_write_u32(vs, 0);
  38.276 +    memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
  38.277 +
  38.278 +    /* Calculate the expected challenge response */
  38.279 +    pwlen = strlen(vs->password);
  38.280 +    for (i=0; i<sizeof(key); i++)
  38.281 +        key[i] = i<pwlen ? vs->password[i] : 0;
  38.282 +    deskey(key, EN0);
  38.283 +    for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
  38.284 +        des(response+j, response+j);
  38.285 +
  38.286 +    /* Compare expected vs actual challenge response */
  38.287 +    if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
  38.288 +	VNC_DEBUG("Client challenge reponse did not match\n");
  38.289 +	vnc_write_u32(vs, 1); /* Reject auth */
  38.290 +	if (vs->minor >= 8) {
  38.291 +	    static const char err[] = "Authentication failed";
  38.292 +	    vnc_write_u32(vs, sizeof(err));
  38.293 +	    vnc_write(vs, err, sizeof(err));
  38.294 +	}
  38.295 +	vnc_flush(vs);
  38.296 +	vnc_client_error(vs);
  38.297 +    } else {
  38.298 +	VNC_DEBUG("Accepting VNC challenge response\n");
  38.299 +	vnc_write_u32(vs, 0); /* Accept auth */
  38.300 +	vnc_flush(vs);
  38.301 +
  38.302 +	vnc_read_when(vs, protocol_client_init, 1);
  38.303 +    }
  38.304 +    return 0;
  38.305 +}
  38.306 +
  38.307 +static int start_auth_vnc(VncState *vs)
  38.308 +{
  38.309 +    make_challenge(vs);
  38.310 +    /* Send client a 'random' challenge */
  38.311 +    vnc_write(vs, vs->challenge, sizeof(vs->challenge));
  38.312      vnc_flush(vs);
  38.313  
  38.314 -    vnc_read_when(vs, protocol_client_init, 1);
  38.315 +    vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
  38.316 +    return 0;
  38.317 +}
  38.318 +
  38.319 +
  38.320 +#if CONFIG_VNC_TLS
  38.321 +#define DH_BITS 1024
  38.322 +static gnutls_dh_params_t dh_params;
  38.323 +
  38.324 +static int vnc_tls_initialize(void)
  38.325 +{
  38.326 +    static int tlsinitialized = 0;
  38.327 +
  38.328 +    if (tlsinitialized)
  38.329 +	return 1;
  38.330 +
  38.331 +    if (gnutls_global_init () < 0)
  38.332 +	return 0;
  38.333 +
  38.334 +    /* XXX ought to re-generate diffie-hellmen params periodically */
  38.335 +    if (gnutls_dh_params_init (&dh_params) < 0)
  38.336 +	return 0;
  38.337 +    if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
  38.338 +	return 0;
  38.339 +
  38.340 +#if _VNC_DEBUG == 2
  38.341 +    gnutls_global_set_log_level(10);
  38.342 +    gnutls_global_set_log_function(vnc_debug_gnutls_log);
  38.343 +#endif
  38.344 +
  38.345 +    tlsinitialized = 1;
  38.346 +
  38.347 +    return 1;
  38.348 +}
  38.349 +
  38.350 +static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
  38.351 +{
  38.352 +    gnutls_anon_server_credentials anon_cred;
  38.353 +    int ret;
  38.354 +
  38.355 +    if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
  38.356 +	VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
  38.357 +	return NULL;
  38.358 +    }
  38.359 +
  38.360 +    gnutls_anon_set_server_dh_params(anon_cred, dh_params);
  38.361 +
  38.362 +    return anon_cred;
  38.363 +}
  38.364 +
  38.365 +
  38.366 +static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState *vs)
  38.367 +{
  38.368 +    gnutls_certificate_credentials_t x509_cred;
  38.369 +    int ret;
  38.370 +
  38.371 +    if (!vs->x509cacert) {
  38.372 +	VNC_DEBUG("No CA x509 certificate specified\n");
  38.373 +	return NULL;
  38.374 +    }
  38.375 +    if (!vs->x509cert) {
  38.376 +	VNC_DEBUG("No server x509 certificate specified\n");
  38.377 +	return NULL;
  38.378 +    }
  38.379 +    if (!vs->x509key) {
  38.380 +	VNC_DEBUG("No server private key specified\n");
  38.381 +	return NULL;
  38.382 +    }
  38.383 +
  38.384 +    if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
  38.385 +	VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
  38.386 +	return NULL;
  38.387 +    }
  38.388 +    if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
  38.389 +						      vs->x509cacert,
  38.390 +						      GNUTLS_X509_FMT_PEM)) < 0) {
  38.391 +	VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
  38.392 +	gnutls_certificate_free_credentials(x509_cred);
  38.393 +	return NULL;
  38.394 +    }
  38.395 +
  38.396 +    if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
  38.397 +						     vs->x509cert,
  38.398 +						     vs->x509key,
  38.399 +						     GNUTLS_X509_FMT_PEM)) < 0) {
  38.400 +	VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
  38.401 +	gnutls_certificate_free_credentials(x509_cred);
  38.402 +	return NULL;
  38.403 +    }
  38.404 +
  38.405 +    if (vs->x509cacrl) {
  38.406 +	if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
  38.407 +							vs->x509cacrl,
  38.408 +							GNUTLS_X509_FMT_PEM)) < 0) {
  38.409 +	    VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
  38.410 +	    gnutls_certificate_free_credentials(x509_cred);
  38.411 +	    return NULL;
  38.412 +	}
  38.413 +    }
  38.414 +
  38.415 +    gnutls_certificate_set_dh_params (x509_cred, dh_params);
  38.416 +
  38.417 +    return x509_cred;
  38.418 +}
  38.419 +
  38.420 +static int vnc_validate_certificate(struct VncState *vs)
  38.421 +{
  38.422 +    int ret;
  38.423 +    unsigned int status;
  38.424 +    const gnutls_datum_t *certs;
  38.425 +    unsigned int nCerts, i;
  38.426 +    time_t now;
  38.427 +
  38.428 +    VNC_DEBUG("Validating client certificate\n");
  38.429 +    if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) {
  38.430 +	VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
  38.431 +	return -1;
  38.432 +    }
  38.433 +
  38.434 +    if ((now = time(NULL)) == ((time_t)-1)) {
  38.435 +	return -1;
  38.436 +    }
  38.437 +
  38.438 +    if (status != 0) {
  38.439 +	if (status & GNUTLS_CERT_INVALID)
  38.440 +	    VNC_DEBUG("The certificate is not trusted.\n");
  38.441 +
  38.442 +	if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
  38.443 +	    VNC_DEBUG("The certificate hasn't got a known issuer.\n");
  38.444 +
  38.445 +	if (status & GNUTLS_CERT_REVOKED)
  38.446 +	    VNC_DEBUG("The certificate has been revoked.\n");
  38.447 +
  38.448 +	if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
  38.449 +	    VNC_DEBUG("The certificate uses an insecure algorithm\n");
  38.450 +
  38.451 +	return -1;
  38.452 +    } else {
  38.453 +	VNC_DEBUG("Certificate is valid!\n");
  38.454 +    }
  38.455 +
  38.456 +    /* Only support x509 for now */
  38.457 +    if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
  38.458 +	return -1;
  38.459 +
  38.460 +    if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
  38.461 +	return -1;
  38.462 +
  38.463 +    for (i = 0 ; i < nCerts ; i++) {
  38.464 +	gnutls_x509_crt_t cert;
  38.465 +	VNC_DEBUG ("Checking certificate chain %d\n", i);
  38.466 +	if (gnutls_x509_crt_init (&cert) < 0)
  38.467 +	    return -1;
  38.468 +
  38.469 +	if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
  38.470 +	    gnutls_x509_crt_deinit (cert);
  38.471 +	    return -1;
  38.472 +	}
  38.473 +
  38.474 +	if (gnutls_x509_crt_get_expiration_time (cert) < now) {
  38.475 +	    VNC_DEBUG("The certificate has expired\n");
  38.476 +	    gnutls_x509_crt_deinit (cert);
  38.477 +	    return -1;
  38.478 +	}
  38.479 +
  38.480 +	if (gnutls_x509_crt_get_activation_time (cert) > now) {
  38.481 +	    VNC_DEBUG("The certificate is not yet activated\n");
  38.482 +	    gnutls_x509_crt_deinit (cert);
  38.483 +	    return -1;
  38.484 +	}
  38.485 +
  38.486 +	if (gnutls_x509_crt_get_activation_time (cert) > now) {
  38.487 +	    VNC_DEBUG("The certificate is not yet activated\n");
  38.488 +	    gnutls_x509_crt_deinit (cert);
  38.489 +	    return -1;
  38.490 +	}
  38.491 +
  38.492 +	gnutls_x509_crt_deinit (cert);
  38.493 +    }
  38.494 +
  38.495 +    return 0;
  38.496 +}
  38.497 +
  38.498 +
  38.499 +static int start_auth_vencrypt_subauth(VncState *vs)
  38.500 +{
  38.501 +    switch (vs->subauth) {
  38.502 +    case VNC_AUTH_VENCRYPT_TLSNONE:
  38.503 +    case VNC_AUTH_VENCRYPT_X509NONE:
  38.504 +       VNC_DEBUG("Accept TLS auth none\n");
  38.505 +       vnc_write_u32(vs, 0); /* Accept auth completion */
  38.506 +       vnc_read_when(vs, protocol_client_init, 1);
  38.507 +       break;
  38.508 +
  38.509 +    case VNC_AUTH_VENCRYPT_TLSVNC:
  38.510 +    case VNC_AUTH_VENCRYPT_X509VNC:
  38.511 +       VNC_DEBUG("Start TLS auth VNC\n");
  38.512 +       return start_auth_vnc(vs);
  38.513 +
  38.514 +    default: /* Should not be possible, but just in case */
  38.515 +       VNC_DEBUG("Reject auth %d\n", vs->auth);
  38.516 +       vnc_write_u8(vs, 1);
  38.517 +       if (vs->minor >= 8) {
  38.518 +           static const char err[] = "Unsupported authentication type";
  38.519 +           vnc_write_u32(vs, sizeof(err));
  38.520 +           vnc_write(vs, err, sizeof(err));
  38.521 +       }
  38.522 +       vnc_client_error(vs);
  38.523 +    }
  38.524  
  38.525      return 0;
  38.526  }
  38.527  
  38.528 -static int protocol_version(VncState *vs, uint8_t *version, size_t len)
  38.529 +static void vnc_handshake_io(void *opaque);
  38.530 +
  38.531 +static int vnc_continue_handshake(struct VncState *vs) {
  38.532 +    int ret;
  38.533 +
  38.534 +    if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
  38.535 +       if (!gnutls_error_is_fatal(ret)) {
  38.536 +           VNC_DEBUG("Handshake interrupted (blocking)\n");
  38.537 +           if (!gnutls_record_get_direction(vs->tls_session))
  38.538 +               qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
  38.539 +           else
  38.540 +               qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
  38.541 +           return 0;
  38.542 +       }
  38.543 +       VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
  38.544 +       vnc_client_error(vs);
  38.545 +       return -1;
  38.546 +    }
  38.547 +
  38.548 +    if (vs->x509verify) {
  38.549 +	if (vnc_validate_certificate(vs) < 0) {
  38.550 +	    VNC_DEBUG("Client verification failed\n");
  38.551 +	    vnc_client_error(vs);
  38.552 +	    return -1;
  38.553 +	} else {
  38.554 +	    VNC_DEBUG("Client verification passed\n");
  38.555 +	}
  38.556 +    }
  38.557 +
  38.558 +    VNC_DEBUG("Handshake done, switching to TLS data mode\n");
  38.559 +    vs->wiremode = VNC_WIREMODE_TLS;
  38.560 +    qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs);
  38.561 +
  38.562 +    return start_auth_vencrypt_subauth(vs);
  38.563 +}
  38.564 +
  38.565 +static void vnc_handshake_io(void *opaque) {
  38.566 +    struct VncState *vs = (struct VncState *)opaque;
  38.567 +
  38.568 +    VNC_DEBUG("Handshake IO continue\n");
  38.569 +    vnc_continue_handshake(vs);
  38.570 +}
  38.571 +
  38.572 +#define NEED_X509_AUTH(vs)			      \
  38.573 +    ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE ||   \
  38.574 +     (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC ||    \
  38.575 +     (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
  38.576 +
  38.577 +
  38.578 +static int vnc_start_tls(struct VncState *vs) {
  38.579 +    static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
  38.580 +    static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 };
  38.581 +    static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
  38.582 +    static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
  38.583 +
  38.584 +    VNC_DEBUG("Do TLS setup\n");
  38.585 +    if (vnc_tls_initialize() < 0) {
  38.586 +	VNC_DEBUG("Failed to init TLS\n");
  38.587 +	vnc_client_error(vs);
  38.588 +	return -1;
  38.589 +    }
  38.590 +    if (vs->tls_session == NULL) {
  38.591 +	if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
  38.592 +	    vnc_client_error(vs);
  38.593 +	    return -1;
  38.594 +	}
  38.595 +
  38.596 +	if (gnutls_set_default_priority(vs->tls_session) < 0) {
  38.597 +	    gnutls_deinit(vs->tls_session);
  38.598 +	    vs->tls_session = NULL;
  38.599 +	    vnc_client_error(vs);
  38.600 +	    return -1;
  38.601 +	}
  38.602 +
  38.603 +	if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) {
  38.604 +	    gnutls_deinit(vs->tls_session);
  38.605 +	    vs->tls_session = NULL;
  38.606 +	    vnc_client_error(vs);
  38.607 +	    return -1;
  38.608 +	}
  38.609 +
  38.610 +	if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) {
  38.611 +	    gnutls_deinit(vs->tls_session);
  38.612 +	    vs->tls_session = NULL;
  38.613 +	    vnc_client_error(vs);
  38.614 +	    return -1;
  38.615 +	}
  38.616 +
  38.617 +	if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) {
  38.618 +	    gnutls_deinit(vs->tls_session);
  38.619 +	    vs->tls_session = NULL;
  38.620 +	    vnc_client_error(vs);
  38.621 +	    return -1;
  38.622 +	}
  38.623 +
  38.624 +	if (NEED_X509_AUTH(vs)) {
  38.625 +	    gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(vs);
  38.626 +	    if (!x509_cred) {
  38.627 +		gnutls_deinit(vs->tls_session);
  38.628 +		vs->tls_session = NULL;
  38.629 +		vnc_client_error(vs);
  38.630 +		return -1;
  38.631 +	    }
  38.632 +	    if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) {
  38.633 +		gnutls_deinit(vs->tls_session);
  38.634 +		vs->tls_session = NULL;
  38.635 +		gnutls_certificate_free_credentials(x509_cred);
  38.636 +		vnc_client_error(vs);
  38.637 +		return -1;
  38.638 +	    }
  38.639 +	    if (vs->x509verify) {
  38.640 +		VNC_DEBUG("Requesting a client certificate\n");
  38.641 +		gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST);
  38.642 +	    }
  38.643 +
  38.644 +	} else {
  38.645 +	    gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred();
  38.646 +	    if (!anon_cred) {
  38.647 +		gnutls_deinit(vs->tls_session);
  38.648 +		vs->tls_session = NULL;
  38.649 +		vnc_client_error(vs);
  38.650 +		return -1;
  38.651 +	    }
  38.652 +	    if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) {
  38.653 +		gnutls_deinit(vs->tls_session);
  38.654 +		vs->tls_session = NULL;
  38.655 +		gnutls_anon_free_server_credentials(anon_cred);
  38.656 +		vnc_client_error(vs);
  38.657 +		return -1;
  38.658 +	    }
  38.659 +	}
  38.660 +
  38.661 +	gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
  38.662 +	gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
  38.663 +	gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
  38.664 +    }
  38.665 +
  38.666 +    VNC_DEBUG("Start TLS handshake process\n");
  38.667 +    return vnc_continue_handshake(vs);
  38.668 +}
  38.669 +
  38.670 +static int protocol_client_vencrypt_auth(VncState *vs, char *data, size_t len)
  38.671  {
  38.672 -    extern char vncpasswd[64];
  38.673 -    extern unsigned char challenge[AUTHCHALLENGESIZE];
  38.674 +    int auth = read_u32(data, 0);
  38.675 +
  38.676 +    if (auth != vs->subauth) {
  38.677 +	VNC_DEBUG("Rejecting auth %d\n", auth);
  38.678 +	vnc_write_u8(vs, 0); /* Reject auth */
  38.679 +	vnc_flush(vs);
  38.680 +	vnc_client_error(vs);
  38.681 +    } else {
  38.682 +	VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
  38.683 +	vnc_write_u8(vs, 1); /* Accept auth */
  38.684 +	vnc_flush(vs);
  38.685 +
  38.686 +	if (vnc_start_tls(vs) < 0) {
  38.687 +	    VNC_DEBUG("Failed to complete TLS\n");
  38.688 +	    return 0;
  38.689 +	}
  38.690 +
  38.691 +	if (vs->wiremode == VNC_WIREMODE_TLS) {
  38.692 +	    VNC_DEBUG("Starting VeNCrypt subauth\n");
  38.693 +	    return start_auth_vencrypt_subauth(vs);
  38.694 +	} else {
  38.695 +	    VNC_DEBUG("TLS handshake blocked\n");
  38.696 +	    return 0;
  38.697 +	}
  38.698 +    }
  38.699 +    return 0;
  38.700 +}
  38.701 +
  38.702 +static int protocol_client_vencrypt_init(VncState *vs, char *data, size_t len)
  38.703 +{
  38.704 +    if (data[0] != 0 ||
  38.705 +	data[1] != 2) {
  38.706 +	VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]);
  38.707 +	vnc_write_u8(vs, 1); /* Reject version */
  38.708 +	vnc_flush(vs);
  38.709 +	vnc_client_error(vs);
  38.710 +    } else {
  38.711 +	VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
  38.712 +	vnc_write_u8(vs, 0); /* Accept version */
  38.713 +	vnc_write_u8(vs, 1); /* Number of sub-auths */
  38.714 +	vnc_write_u32(vs, vs->subauth); /* The supported auth */
  38.715 +	vnc_flush(vs);
  38.716 +	vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
  38.717 +    }
  38.718 +    return 0;
  38.719 +}
  38.720 +
  38.721 +static int start_auth_vencrypt(VncState *vs)
  38.722 +{
  38.723 +    /* Send VeNCrypt version 0.2 */
  38.724 +    vnc_write_u8(vs, 0);
  38.725 +    vnc_write_u8(vs, 2);
  38.726 +
  38.727 +    vnc_read_when(vs, protocol_client_vencrypt_init, 2);
  38.728 +    return 0;
  38.729 +}
  38.730 +#endif /* CONFIG_VNC_TLS */
  38.731 +
  38.732 +static int protocol_client_auth(VncState *vs, char *data, size_t len)
  38.733 +{
  38.734 +    /* We only advertise 1 auth scheme at a time, so client
  38.735 +     * must pick the one we sent. Verify this */
  38.736 +    if (data[0] != vs->auth) { /* Reject auth */
  38.737 +       VNC_DEBUG("Reject auth %d\n", (int)data[0]);
  38.738 +       vnc_write_u32(vs, 1);
  38.739 +       if (vs->minor >= 8) {
  38.740 +           static const char err[] = "Authentication failed";
  38.741 +           vnc_write_u32(vs, sizeof(err));
  38.742 +           vnc_write(vs, err, sizeof(err));
  38.743 +       }
  38.744 +       vnc_client_error(vs);
  38.745 +    } else { /* Accept requested auth */
  38.746 +       VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
  38.747 +       switch (vs->auth) {
  38.748 +       case VNC_AUTH_NONE:
  38.749 +           VNC_DEBUG("Accept auth none\n");
  38.750 +           if (vs->minor >= 8) {
  38.751 +               vnc_write_u32(vs, 0); /* Accept auth completion */
  38.752 +               vnc_flush(vs);
  38.753 +           }
  38.754 +           vnc_read_when(vs, protocol_client_init, 1);
  38.755 +           break;
  38.756 +
  38.757 +       case VNC_AUTH_VNC:
  38.758 +           VNC_DEBUG("Start VNC auth\n");
  38.759 +           return start_auth_vnc(vs);
  38.760 +
  38.761 +#if CONFIG_VNC_TLS
  38.762 +       case VNC_AUTH_VENCRYPT:
  38.763 +           VNC_DEBUG("Accept VeNCrypt auth\n");;
  38.764 +           return start_auth_vencrypt(vs);
  38.765 +#endif /* CONFIG_VNC_TLS */
  38.766 +
  38.767 +       default: /* Should not be possible, but just in case */
  38.768 +           VNC_DEBUG("Reject auth %d\n", vs->auth);
  38.769 +           vnc_write_u8(vs, 1);
  38.770 +           if (vs->minor >= 8) {
  38.771 +               static const char err[] = "Authentication failed";
  38.772 +               vnc_write_u32(vs, sizeof(err));
  38.773 +               vnc_write(vs, err, sizeof(err));
  38.774 +           }
  38.775 +           vnc_client_error(vs);
  38.776 +       }
  38.777 +    }
  38.778 +    return 0;
  38.779 +}
  38.780 +
  38.781 +static int protocol_version(VncState *vs, char *version, size_t len)
  38.782 +{
  38.783      char local[13];
  38.784 -    int  support, maj, min;
  38.785  
  38.786      memcpy(local, version, 12);
  38.787      local[12] = 0;
  38.788  
  38.789 -    /* protocol version check */
  38.790 -    if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
  38.791 -	fprintf(stderr, "Protocol version error.\n");
  38.792 +    if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
  38.793 +	VNC_DEBUG("Malformed protocol version %s\n", local);
  38.794 +	vnc_client_error(vs);
  38.795 +	return 0;
  38.796 +    }
  38.797 +    VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
  38.798 +    if (vs->major != 3 ||
  38.799 +	(vs->minor != 3 &&
  38.800 +	 vs->minor != 4 &&
  38.801 +	 vs->minor != 5 &&
  38.802 +	 vs->minor != 7 &&
  38.803 +	 vs->minor != 8)) {
  38.804 +	VNC_DEBUG("Unsupported client version\n");
  38.805 +	vnc_write_u32(vs, VNC_AUTH_INVALID);
  38.806 +	vnc_flush(vs);
  38.807  	vnc_client_error(vs);
  38.808  	return 0;
  38.809      }
  38.810 -
  38.811 -
  38.812 -    support = 0;
  38.813 -    if (maj == 3) {
  38.814 -	if (min == 3 || min ==4) {
  38.815 -	    support = 1;
  38.816 -	}
  38.817 -    }
  38.818 -
  38.819 -    if (! support) {
  38.820 -	fprintf(stderr, "Client uses unsupported protocol version %d.%d.\n",
  38.821 -		maj, min);
  38.822 -	vnc_client_error(vs);
  38.823 -	return 0;
  38.824 -    }
  38.825 +    /* Some broken clients report v3.4 or v3.5, which spec requires to be treated
  38.826 +     * as equivalent to v3.3 by servers
  38.827 +     */
  38.828 +    if (vs->minor == 4 || vs->minor == 5)
  38.829 +	vs->minor = 3;
  38.830  
  38.831 -    if (*vncpasswd == '\0') {
  38.832 -	/* AuthType is None */
  38.833 -	vnc_write_u32(vs, 1);
  38.834 -	vnc_flush(vs);
  38.835 -	vnc_read_when(vs, protocol_client_init, 1);
  38.836 +    if (vs->minor == 3) {
  38.837 +	if (vs->auth == VNC_AUTH_NONE) {
  38.838 +            VNC_DEBUG("Tell client auth none\n");
  38.839 +            vnc_write_u32(vs, vs->auth);
  38.840 +            vnc_flush(vs);
  38.841 +            vnc_read_when(vs, protocol_client_init, 1);
  38.842 +       } else if (vs->auth == VNC_AUTH_VNC) {
  38.843 +            VNC_DEBUG("Tell client VNC auth\n");
  38.844 +            vnc_write_u32(vs, vs->auth);
  38.845 +            vnc_flush(vs);
  38.846 +            start_auth_vnc(vs);
  38.847 +       } else {
  38.848 +            VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
  38.849 +            vnc_write_u32(vs, VNC_AUTH_INVALID);
  38.850 +            vnc_flush(vs);
  38.851 +            vnc_client_error(vs);
  38.852 +       }
  38.853      } else {
  38.854 -	/* AuthType is VncAuth */
  38.855 -	vnc_write_u32(vs, 2);
  38.856 -
  38.857 -	/* Challenge-Responce authentication */
  38.858 -	/* Send Challenge */
  38.859 -	make_challenge(challenge, AUTHCHALLENGESIZE);
  38.860 -	vnc_write(vs, challenge, AUTHCHALLENGESIZE);
  38.861 +	VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
  38.862 +	vnc_write_u8(vs, 1); /* num auth */
  38.863 +	vnc_write_u8(vs, vs->auth);
  38.864 +	vnc_read_when(vs, protocol_client_auth, 1);
  38.865  	vnc_flush(vs);
  38.866 -	vnc_read_when(vs, protocol_response, AUTHCHALLENGESIZE);
  38.867      }
  38.868  
  38.869      return 0;
  38.870 @@ -1485,9 +2129,10 @@ static void vnc_listen_read(void *opaque
  38.871  
  38.872      vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
  38.873      if (vs->csock != -1) {
  38.874 +	VNC_DEBUG("New client on socket %d\n", vs->csock);
  38.875          socket_set_nonblock(vs->csock);
  38.876  	qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
  38.877 -	vnc_write(vs, "RFB 003.003\n", 12);
  38.878 +	vnc_write(vs, "RFB 003.008\n", 12);
  38.879  	vnc_flush(vs);
  38.880  	vnc_read_when(vs, protocol_version, 12);
  38.881  	framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
  38.882 @@ -1500,16 +2145,8 @@ static void vnc_listen_read(void *opaque
  38.883  
  38.884  extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
  38.885  
  38.886 -int vnc_display_init(DisplayState *ds, const char *arg, int find_unused)
  38.887 +void vnc_display_init(DisplayState *ds)
  38.888  {
  38.889 -    struct sockaddr *addr;
  38.890 -    struct sockaddr_in iaddr;
  38.891 -#ifndef _WIN32
  38.892 -    struct sockaddr_un uaddr;
  38.893 -#endif
  38.894 -    int reuse_addr, ret;
  38.895 -    socklen_t addrlen;
  38.896 -    const char *p;
  38.897      VncState *vs;
  38.898  
  38.899      vs = qemu_mallocz(sizeof(VncState));
  38.900 @@ -1518,7 +2155,8 @@ int vnc_display_init(DisplayState *ds, c
  38.901  
  38.902      ds->opaque = vs;
  38.903      vnc_state = vs;
  38.904 -    vs->display = arg;
  38.905 +    vs->display = NULL;
  38.906 +    vs->password = NULL;
  38.907  
  38.908      vs->lsock = -1;
  38.909      vs->csock = -1;
  38.910 @@ -1542,19 +2180,238 @@ int vnc_display_init(DisplayState *ds, c
  38.911      vs->ds->dpy_refresh = vnc_dpy_refresh;
  38.912  
  38.913      vnc_dpy_resize(vs->ds, 640, 400);
  38.914 +}
  38.915  
  38.916 -    if (arg == NULL)
  38.917 -	arg = "localhost:0";
  38.918 -    
  38.919 +#if CONFIG_VNC_TLS
  38.920 +static int vnc_set_x509_credential(VncState *vs,
  38.921 +				   const char *certdir,
  38.922 +				   const char *filename,
  38.923 +				   char **cred,
  38.924 +				   int ignoreMissing)
  38.925 +{
  38.926 +    struct stat sb;
  38.927 +
  38.928 +    if (*cred) {
  38.929 +	qemu_free(*cred);
  38.930 +	*cred = NULL;
  38.931 +    }
  38.932 +
  38.933 +    if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
  38.934 +	return -1;
  38.935 +
  38.936 +    strcpy(*cred, certdir);
  38.937 +    strcat(*cred, "/");
  38.938 +    strcat(*cred, filename);
  38.939 +
  38.940 +    VNC_DEBUG("Check %s\n", *cred);
  38.941 +    if (stat(*cred, &sb) < 0) {
  38.942 +	qemu_free(*cred);
  38.943 +	*cred = NULL;
  38.944 +	if (ignoreMissing && errno == ENOENT)
  38.945 +	    return 0;
  38.946 +	return -1;
  38.947 +    }
  38.948 +
  38.949 +    return 0;
  38.950 +}
  38.951 +
  38.952 +static int vnc_set_x509_credential_dir(VncState *vs,
  38.953 +				       const char *certdir)
  38.954 +{
  38.955 +    if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE, &vs->x509cacert, 0) < 0)
  38.956 +	goto cleanup;
  38.957 +    if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl, 1) < 0)
  38.958 +	goto cleanup;
  38.959 +    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE, &vs->x509cert, 0) < 0)
  38.960 +	goto cleanup;
  38.961 +    if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE, &vs->x509key, 0) < 0)
  38.962 +	goto cleanup;
  38.963 +
  38.964 +    return 0;
  38.965 +
  38.966 + cleanup:
  38.967 +    qemu_free(vs->x509cacert);
  38.968 +    qemu_free(vs->x509cacrl);
  38.969 +    qemu_free(vs->x509cert);
  38.970 +    qemu_free(vs->x509key);
  38.971 +    vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
  38.972 +    return -1;
  38.973 +}
  38.974 +#endif /* CONFIG_VNC_TLS */
  38.975 +
  38.976 +void vnc_display_close(DisplayState *ds)
  38.977 +{
  38.978 +    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
  38.979 +
  38.980 +    if (vs->display) {
  38.981 +	qemu_free(vs->display);
  38.982 +	vs->display = NULL;
  38.983 +    }
  38.984 +    if (vs->lsock != -1) {
  38.985 +	qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
  38.986 +	close(vs->lsock);
  38.987 +	vs->lsock = -1;
  38.988 +    }
  38.989 +    if (vs->csock != -1) {
  38.990 +	qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
  38.991 +	closesocket(vs->csock);
  38.992 +	vs->csock = -1;
  38.993 +	buffer_reset(&vs->input);
  38.994 +	buffer_reset(&vs->output);
  38.995 +#if CONFIG_VNC_TLS
  38.996 +	if (vs->tls_session) {
  38.997 +	    gnutls_deinit(vs->tls_session);
  38.998 +	    vs->tls_session = NULL;
  38.999 +	}
 38.1000 +	vs->wiremode = VNC_WIREMODE_CLEAR;
 38.1001 +#endif /* CONFIG_VNC_TLS */
 38.1002 +    }
 38.1003 +    vs->auth = VNC_AUTH_INVALID;
 38.1004 +#if CONFIG_VNC_TLS
 38.1005 +    vs->subauth = VNC_AUTH_INVALID;
 38.1006 +    vs->x509verify = 0;
 38.1007 +#endif
 38.1008 +}
 38.1009 +
 38.1010 +int parse_host_port(struct sockaddr_in *saddr, const char *str);
 38.1011 +
 38.1012 +
 38.1013 +
 38.1014 +int vnc_display_password(DisplayState *ds, const char *password)
 38.1015 +{
 38.1016 +    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
 38.1017 +
 38.1018 +    if (vs->password) {
 38.1019 +	qemu_free(vs->password);
 38.1020 +	vs->password = NULL;
 38.1021 +    }
 38.1022 +    if (password && password[0]) {
 38.1023 +	if (!(vs->password = qemu_strdup(password)))
 38.1024 +	    return -1;
 38.1025 +    }
 38.1026 +
 38.1027 +    return 0;
 38.1028 +}
 38.1029 +
 38.1030 +int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
 38.1031 +{
 38.1032 +    struct sockaddr *addr;
 38.1033 +    struct sockaddr_in iaddr;
 38.1034  #ifndef _WIN32
 38.1035 -    if (strstart(arg, "unix:", &p)) {
 38.1036 +    struct sockaddr_un uaddr;
 38.1037 +#endif
 38.1038 +    int reuse_addr, ret;
 38.1039 +    socklen_t addrlen;
 38.1040 +    const char *p;
 38.1041 +    VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
 38.1042 +    const char *options;
 38.1043 +    int password = 0;
 38.1044 +#if CONFIG_VNC_TLS
 38.1045 +    int tls = 0, x509 = 0;
 38.1046 +#endif
 38.1047 +
 38.1048 +    if (display == NULL)
 38.1049 +	display = "localhost:0";
 38.1050 +
 38.1051 +    vnc_display_close(ds);
 38.1052 +    if (strcmp(display, "none") == 0)
 38.1053 +        return 0;
 38.1054 +
 38.1055 +    if (!(vs->display = strdup(display)))
 38.1056 +        return -1;
 38.1057 +
 38.1058 +    options = display;
 38.1059 +    while ((options = strchr(options, ','))) {
 38.1060 +	options++;
 38.1061 +	if (strncmp(options, "password", 8) == 0) {
 38.1062 +	    password = 1; /* Require password auth */
 38.1063 +#if CONFIG_VNC_TLS
 38.1064 +	} else if (strncmp(options, "tls", 3) == 0) {
 38.1065 +	    tls = 1; /* Require TLS */
 38.1066 +	} else if (strncmp(options, "x509", 4) == 0) {
 38.1067 +	    char *start, *end;
 38.1068 +	    x509 = 1; /* Require x509 certificates */
 38.1069 +	    if (strncmp(options, "x509verify", 10) == 0)
 38.1070 +	        vs->x509verify = 1; /* ...and verify client certs */
 38.1071 +
 38.1072 +	    /* Now check for 'x509=/some/path' postfix
 38.1073 +	     * and use that to setup x509 certificate/key paths */
 38.1074 +	    start = strchr(options, '=');
 38.1075 +	    end = strchr(options, ',');
 38.1076 +	    if (start && (!end || (start < end))) {
 38.1077 +		int len = end ? end-(start+1) : strlen(start+1);
 38.1078 +		char *path = qemu_malloc(len+1);
 38.1079 +		strncpy(path, start+1, len);
 38.1080 +		path[len] = '\0';
 38.1081 +		VNC_DEBUG("Trying certificate path '%s'\n", path);
 38.1082 +		if (vnc_set_x509_credential_dir(vs, path) < 0) {
 38.1083 +		    fprintf(stderr, "Failed to find x509 certificates/keys in %s\n", path);
 38.1084 +		    qemu_free(path);
 38.1085 +		    qemu_free(vs->display);
 38.1086 +		    vs->display = NULL;
 38.1087 +		    return -1;
 38.1088 +		}
 38.1089 +		qemu_free(path);
 38.1090 +	    } else {
 38.1091 +		fprintf(stderr, "No certificate path provided\n");
 38.1092 +		qemu_free(vs->display);
 38.1093 +		vs->display = NULL;
 38.1094 +		return -1;
 38.1095 +	    }
 38.1096 +#endif
 38.1097 +	}
 38.1098 +    }
 38.1099 +
 38.1100 +    if (password) {
 38.1101 +#if CONFIG_VNC_TLS
 38.1102 +	if (tls) {
 38.1103 +	    vs->auth = VNC_AUTH_VENCRYPT;
 38.1104 +	    if (x509) {
 38.1105 +		VNC_DEBUG("Initializing VNC server with x509 password auth\n");
 38.1106 +		vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
 38.1107 +	    } else {
 38.1108 +		VNC_DEBUG("Initializing VNC server with TLS password auth\n");
 38.1109 +		vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
 38.1110 +	    }
 38.1111 +	} else {
 38.1112 +#endif
 38.1113 +	    VNC_DEBUG("Initializing VNC server with password auth\n");
 38.1114 +	    vs->auth = VNC_AUTH_VNC;
 38.1115 +#if CONFIG_VNC_TLS
 38.1116 +	    vs->subauth = VNC_AUTH_INVALID;
 38.1117 +	}
 38.1118 +#endif
 38.1119 +    } else {
 38.1120 +#if CONFIG_VNC_TLS
 38.1121 +	if (tls) {
 38.1122 +	    vs->auth = VNC_AUTH_VENCRYPT;
 38.1123 +	    if (x509) {
 38.1124 +		VNC_DEBUG("Initializing VNC server with x509 no auth\n");
 38.1125 +		vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
 38.1126 +	    } else {
 38.1127 +		VNC_DEBUG("Initializing VNC server with TLS no auth\n");
 38.1128 +		vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
 38.1129 +	    }
 38.1130 +	} else {
 38.1131 +#endif
 38.1132 +	    VNC_DEBUG("Initializing VNC server with no auth\n");
 38.1133 +	    vs->auth = VNC_AUTH_NONE;
 38.1134 +#if CONFIG_VNC_TLS
 38.1135 +	    vs->subauth = VNC_AUTH_INVALID;
 38.1136 +	}
 38.1137 +#endif
 38.1138 +    }
 38.1139 +#ifndef _WIN32
 38.1140 +    if (strstart(display, "unix:", &p)) {
 38.1141  	addr = (struct sockaddr *)&uaddr;
 38.1142  	addrlen = sizeof(uaddr);
 38.1143  
 38.1144  	vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
 38.1145  	if (vs->lsock == -1) {
 38.1146  	    fprintf(stderr, "Could not create socket\n");
 38.1147 -	    exit(1);
 38.1148 +	    free(vs->display);
 38.1149 +	    vs->display = NULL;
 38.1150 +	    return -1;
 38.1151  	}
 38.1152  
 38.1153  	uaddr.sun_family = AF_UNIX;
 38.1154 @@ -1568,25 +2425,33 @@ int vnc_display_init(DisplayState *ds, c
 38.1155  	addr = (struct sockaddr *)&iaddr;
 38.1156  	addrlen = sizeof(iaddr);
 38.1157  
 38.1158 +	if (parse_host_port(&iaddr, display) < 0) {
 38.1159 +	    fprintf(stderr, "Could not parse VNC address\n");
 38.1160 +	    free(vs->display);
 38.1161 +	    vs->display = NULL;
 38.1162 +	    return -1;
 38.1163 +	}
 38.1164 +
 38.1165 +	iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
 38.1166 +
 38.1167  	vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
 38.1168  	if (vs->lsock == -1) {
 38.1169  	    fprintf(stderr, "Could not create socket\n");
 38.1170 -	    exit(1);
 38.1171 +	    free(vs->display);
 38.1172 +	    vs->display = NULL;
 38.1173 +	    return -1;
 38.1174  	}
 38.1175  
 38.1176 -	if (parse_host_port(&iaddr, arg) < 0) {
 38.1177 -	    fprintf(stderr, "Could not parse VNC address\n");
 38.1178 -	    exit(1);
 38.1179 -	}
 38.1180 -	    
 38.1181 -	iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
 38.1182 -
 38.1183  	reuse_addr = 1;
 38.1184  	ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
 38.1185  			 (const char *)&reuse_addr, sizeof(reuse_addr));
 38.1186  	if (ret == -1) {
 38.1187  	    fprintf(stderr, "setsockopt() failed\n");
 38.1188 -	    exit(1);
 38.1189 +	    close(vs->lsock);
 38.1190 +	    vs->lsock = -1;
 38.1191 +	    free(vs->display);
 38.1192 +	    vs->display = NULL;
 38.1193 +	    return -1;
 38.1194  	}
 38.1195      }
 38.1196  
 38.1197 @@ -1596,18 +2461,24 @@ int vnc_display_init(DisplayState *ds, c
 38.1198  	    continue;
 38.1199  	}
 38.1200  	fprintf(stderr, "bind() failed\n");
 38.1201 -	exit(1);
 38.1202 +	close(vs->lsock);
 38.1203 +	vs->lsock = -1;
 38.1204 +	free(vs->display);
 38.1205 +	vs->display = NULL;
 38.1206 +	return -1;
 38.1207      }
 38.1208  
 38.1209      if (listen(vs->lsock, 1) == -1) {
 38.1210  	fprintf(stderr, "listen() failed\n");
 38.1211 -	exit(1);
 38.1212 +	close(vs->lsock);
 38.1213 +	vs->lsock = -1;
 38.1214 +	free(vs->display);
 38.1215 +	vs->display = NULL;
 38.1216 +	return -1;
 38.1217      }
 38.1218  
 38.1219 -    ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs);
 38.1220 -    if (ret == -1) {
 38.1221 -	exit(1);
 38.1222 -    }
 38.1223 +    if (qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs) < 0)
 38.1224 +	return -1;
 38.1225  
 38.1226      return ntohs(iaddr.sin_port);
 38.1227  }
 38.1228 @@ -1640,31 +2511,3 @@ int vnc_start_viewer(int port)
 38.1229      }
 38.1230  }
 38.1231  
 38.1232 -unsigned int seed;
 38.1233 -
 38.1234 -static int make_challenge(unsigned char *random, int size)
 38.1235 -{
 38.1236 - 
 38.1237 -    set_seed(&seed);
 38.1238 -    get_random(size, random);
 38.1239 -
 38.1240 -    return 0;
 38.1241 -}
 38.1242 -
 38.1243 -static void set_seed(unsigned int *seedp)
 38.1244 -{
 38.1245 -    *seedp += (unsigned int)(time(NULL)+getpid()+getpid()*987654+rand());
 38.1246 -    srand(*seedp);
 38.1247 -
 38.1248 -    return;
 38.1249 -}
 38.1250 -
 38.1251 -static void get_random(int len, unsigned char *buf)
 38.1252 -{
 38.1253 -    int i;
 38.1254 -
 38.1255 -    for (i=0; i<len; i++)
 38.1256 -	buf[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
 38.1257 -
 38.1258 -    return;
 38.1259 -}
    39.1 --- a/tools/ioemu/xenstore.c	Tue Oct 30 11:33:55 2007 -0600
    39.2 +++ b/tools/ioemu/xenstore.c	Tue Oct 30 15:34:44 2007 -0600
    39.3 @@ -17,7 +17,7 @@
    39.4  #include <sys/stat.h>
    39.5  #include <fcntl.h>
    39.6  
    39.7 -static struct xs_handle *xsh = NULL;
    39.8 +struct xs_handle *xsh = NULL;
    39.9  static char *media_filename[MAX_DISKS + MAX_SCSI_DISKS];
   39.10  static QEMUTimer *insert_timer = NULL;
   39.11  
   39.12 @@ -303,12 +303,19 @@ void xenstore_process_logdirty_event(voi
   39.13          logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
   39.14  
   39.15          /* Map the shared-memory segment */
   39.16 -        if ((shmid = shmget(key, 
   39.17 -                            2 * logdirty_bitmap_size, 
   39.18 -                            S_IRUSR|S_IWUSR)) == -1 
   39.19 -            || (seg = shmat(shmid, NULL, 0)) == (void *)-1) {
   39.20 -            fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n",
   39.21 -                    (unsigned long long) key, strerror(errno));
   39.22 +        fprintf(logfile, "%s: key=%16.16llx size=%d\n", __FUNCTION__,
   39.23 +                (unsigned long long)key, logdirty_bitmap_size);
   39.24 +        shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
   39.25 +        if (shmid == -1) {
   39.26 +            fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
   39.27 +                    "(%s)\n", (unsigned long long)key, strerror(errno));
   39.28 +            exit(1);
   39.29 +        }
   39.30 +
   39.31 +        seg = shmat(shmid, NULL, 0);
   39.32 +        if (seg == (void *)-1) {
   39.33 +            fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
   39.34 +                    "(%s)\n", (unsigned long long)key, strerror(errno));
   39.35              exit(1);
   39.36          }
   39.37  
   39.38 @@ -318,6 +325,9 @@ void xenstore_process_logdirty_event(voi
   39.39          if (logdirty_bitmap_size != *(uint32_t *)seg) {
   39.40              fprintf(logfile, "Log-dirty: got %u, calc %lu\n", 
   39.41                      *(uint32_t *)seg, logdirty_bitmap_size);
   39.42 +            /* Stale key: wait for next watch */
   39.43 +            shmdt(seg);
   39.44 +            seg = NULL;
   39.45              return;
   39.46          }
   39.47  
   39.48 @@ -478,9 +488,8 @@ void xenstore_write_vncport(int display)
   39.49      free(buf);
   39.50  }
   39.51  
   39.52 -int xenstore_read_vncpasswd(int domid)
   39.53 +int xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen)
   39.54  {
   39.55 -    extern char vncpasswd[64];
   39.56      char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
   39.57      unsigned int i, len, rc = 0;
   39.58  
   39.59 @@ -506,16 +515,17 @@ int xenstore_read_vncpasswd(int domid)
   39.60      passwd = xs_read(xsh, XBT_NULL, buf, &len);
   39.61      if (passwd == NULL) {
   39.62          fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
   39.63 +        pwbuf[0] = '\0';
   39.64          free(uuid);
   39.65          free(path);
   39.66          return rc;
   39.67      }
   39.68  
   39.69 -    for (i=0; i<len && i<63; i++) {
   39.70 -        vncpasswd[i] = passwd[i];
   39.71 -        passwd[i] = '\0';
   39.72 +    for (i=0; i<len && i<pwbuflen; i++) {
   39.73 +        pwbuf[i] = passwd[i];
   39.74      }
   39.75 -    vncpasswd[len] = '\0';
   39.76 +    pwbuf[len < (pwbuflen-1) ? len : (pwbuflen-1)] = '\0';
   39.77 +    passwd[0] = '\0';
   39.78      pasprintf(&buf, "%s/vncpasswd", uuid);
   39.79      if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
   39.80          fprintf(logfile, "xs_write() vncpasswd failed.\n");
   39.81 @@ -724,7 +734,7 @@ int xenstore_vm_write(int domid, char *k
   39.82  
   39.83      pasprintf(&buf, "%s/%s", path, key);
   39.84      rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
   39.85 -    if (rc) {
   39.86 +    if (rc == 0) {
   39.87          fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
   39.88          goto out;
   39.89      }
    40.1 --- a/tools/libxc/xc_domain.c	Tue Oct 30 11:33:55 2007 -0600
    40.2 +++ b/tools/libxc/xc_domain.c	Tue Oct 30 15:34:44 2007 -0600
    40.3 @@ -378,9 +378,9 @@ int xc_domain_setmaxmem(int xc_handle,
    40.4  
    40.5  int xc_domain_pin_memory_cacheattr(int xc_handle,
    40.6                                     uint32_t domid,
    40.7 -                                   unsigned long start,
    40.8 -                                   unsigned long end,
    40.9 -                                   unsigned int type)
   40.10 +                                   uint64_t start,
   40.11 +                                   uint64_t end,
   40.12 +                                   uint32_t type)
   40.13  {
   40.14      DECLARE_DOMCTL;
   40.15      domctl.cmd = XEN_DOMCTL_pin_mem_cacheattr;
    41.1 --- a/tools/libxc/xc_domain_restore.c	Tue Oct 30 11:33:55 2007 -0600
    41.2 +++ b/tools/libxc/xc_domain_restore.c	Tue Oct 30 15:34:44 2007 -0600
    41.3 @@ -169,7 +169,8 @@ static int uncanonicalize_pagetable(int 
    41.4  
    41.5  
    41.6  /* Load the p2m frame list, plus potential extended info chunk */
    41.7 -static xen_pfn_t *load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
    41.8 +static xen_pfn_t *load_p2m_frame_list(
    41.9 +    int io_fd, int *pae_extended_cr3, int *ext_vcpucontext)
   41.10  {
   41.11      xen_pfn_t *p2m_frame_list;
   41.12      vcpu_guest_context_either_t ctxt;
   41.13 @@ -200,7 +201,8 @@ static xen_pfn_t *load_p2m_frame_list(in
   41.14              
   41.15              /* 4-character chunk signature + 4-byte remaining chunk size. */
   41.16              if ( !read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
   41.17 -                 !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes)) )
   41.18 +                 !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes)) ||
   41.19 +                 (tot_bytes < (chunk_bytes + 8)) )
   41.20              {
   41.21                  ERROR("read extended-info chunk signature failed");
   41.22                  return NULL;
   41.23 @@ -240,6 +242,10 @@ static xen_pfn_t *load_p2m_frame_list(in
   41.24                       & (1UL << VMASST_TYPE_pae_extended_cr3) )
   41.25                      *pae_extended_cr3 = 1;
   41.26              }
   41.27 +            else if ( !strncmp(chunk_sig, "extv", 4) )
   41.28 +            {
   41.29 +                *ext_vcpucontext = 1;
   41.30 +            }
   41.31              
   41.32              /* Any remaining bytes of this chunk: read and discard. */
   41.33              while ( chunk_bytes )
   41.34 @@ -289,7 +295,7 @@ int xc_domain_restore(int xc_handle, int
   41.35                        unsigned int hvm, unsigned int pae)
   41.36  {
   41.37      DECLARE_DOMCTL;
   41.38 -    int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
   41.39 +    int rc = 1, frc, i, j, n, m, pae_extended_cr3 = 0, ext_vcpucontext = 0;
   41.40      unsigned long mfn, pfn;
   41.41      unsigned int prev_pc, this_pc;
   41.42      int verify = 0;
   41.43 @@ -373,7 +379,8 @@ int xc_domain_restore(int xc_handle, int
   41.44      if ( !hvm ) 
   41.45      {
   41.46          /* Load the p2m frame list, plus potential extended info chunk */
   41.47 -        p2m_frame_list = load_p2m_frame_list(io_fd, &pae_extended_cr3);
   41.48 +        p2m_frame_list = load_p2m_frame_list(
   41.49 +            io_fd, &pae_extended_cr3, &ext_vcpucontext);
   41.50          if ( !p2m_frame_list )
   41.51              goto out;
   41.52  
   41.53 @@ -382,13 +389,12 @@ int xc_domain_restore(int xc_handle, int
   41.54          domctl.domain = dom;
   41.55          domctl.cmd    = XEN_DOMCTL_set_address_size;
   41.56          domctl.u.address_size.size = guest_width * 8;
   41.57 -        rc = do_domctl(xc_handle, &domctl);
   41.58 -        if ( rc != 0 )
   41.59 +        frc = do_domctl(xc_handle, &domctl);
   41.60 +        if ( frc != 0 )
   41.61          {
   41.62              ERROR("Unable to set guest address size.");
   41.63              goto out;
   41.64          }
   41.65 -        rc = 1;
   41.66      }
   41.67  
   41.68      /* We want zeroed memory so use calloc rather than malloc. */
   41.69 @@ -713,18 +719,19 @@ int xc_domain_restore(int xc_handle, int
   41.70              goto out;
   41.71          }
   41.72                  
   41.73 -        if ( (rc = xc_set_hvm_param(xc_handle, dom, 
   41.74 -                                    HVM_PARAM_IOREQ_PFN, magic_pfns[0]))
   41.75 -             || (rc = xc_set_hvm_param(xc_handle, dom, 
   41.76 -                                       HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]))
   41.77 -             || (rc = xc_set_hvm_param(xc_handle, dom, 
   41.78 -                                       HVM_PARAM_STORE_PFN, magic_pfns[2]))
   41.79 -             || (rc = xc_set_hvm_param(xc_handle, dom, 
   41.80 -                                       HVM_PARAM_PAE_ENABLED, pae))
   41.81 -             || (rc = xc_set_hvm_param(xc_handle, dom, 
   41.82 -                                       HVM_PARAM_STORE_EVTCHN, store_evtchn)) )
   41.83 +        if ( (frc = xc_set_hvm_param(xc_handle, dom, 
   41.84 +                                     HVM_PARAM_IOREQ_PFN, magic_pfns[0]))
   41.85 +             || (frc = xc_set_hvm_param(xc_handle, dom, 
   41.86 +                                        HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]))
   41.87 +             || (frc = xc_set_hvm_param(xc_handle, dom, 
   41.88 +                                        HVM_PARAM_STORE_PFN, magic_pfns[2]))
   41.89 +             || (frc = xc_set_hvm_param(xc_handle, dom, 
   41.90 +                                        HVM_PARAM_PAE_ENABLED, pae))
   41.91 +             || (frc = xc_set_hvm_param(xc_handle, dom, 
   41.92 +                                        HVM_PARAM_STORE_EVTCHN,
   41.93 +                                        store_evtchn)) )
   41.94          {
   41.95 -            ERROR("error setting HVM params: %i", rc);
   41.96 +            ERROR("error setting HVM params: %i", frc);
   41.97              goto out;
   41.98          }
   41.99          *store_mfn = magic_pfns[2];
  41.100 @@ -750,10 +757,15 @@ int xc_domain_restore(int xc_handle, int
  41.101              goto out;
  41.102          }
  41.103          
  41.104 -        rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len);
  41.105 -        if ( rc ) 
  41.106 +        frc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len);
  41.107 +        if ( frc )
  41.108 +        {
  41.109              ERROR("error setting the HVM context");
  41.110 -       
  41.111 +            goto out;
  41.112 +        }
  41.113 +
  41.114 +        /* HVM success! */
  41.115 +        rc = 0;
  41.116          goto out;
  41.117      }
  41.118  
  41.119 @@ -929,7 +941,7 @@ int xc_domain_restore(int xc_handle, int
  41.120      {
  41.121          unsigned int count = 0;
  41.122          unsigned long *pfntab;
  41.123 -        int nr_frees, rc;
  41.124 +        int nr_frees;
  41.125  
  41.126          if ( !read_exact(io_fd, &count, sizeof(count)) ||
  41.127               (count > (1U << 28)) ) /* up to 1TB of address space */
  41.128 @@ -973,10 +985,10 @@ int xc_domain_restore(int xc_handle, int
  41.129              };
  41.130              set_xen_guest_handle(reservation.extent_start, pfntab);
  41.131  
  41.132 -            if ( (rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
  41.133 -                                    &reservation)) != nr_frees )
  41.134 +            if ( (frc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
  41.135 +                                     &reservation)) != nr_frees )
  41.136              {
  41.137 -                ERROR("Could not decrease reservation : %d", rc);
  41.138 +                ERROR("Could not decrease reservation : %d", frc);
  41.139                  goto out;
  41.140              }
  41.141              else
  41.142 @@ -1091,13 +1103,29 @@ int xc_domain_restore(int xc_handle, int
  41.143          domctl.domain = (domid_t)dom;
  41.144          domctl.u.vcpucontext.vcpu = i;
  41.145          set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt.c);
  41.146 -        rc = xc_domctl(xc_handle, &domctl);
  41.147 -        if ( rc != 0 )
  41.148 +        frc = xc_domctl(xc_handle, &domctl);
  41.149 +        if ( frc != 0 )
  41.150          {
  41.151              ERROR("Couldn't build vcpu%d", i);
  41.152              goto out;
  41.153          }
  41.154 -        rc = 1;
  41.155 +
  41.156 +        if ( !ext_vcpucontext )
  41.157 +            continue;
  41.158 +        if ( !read_exact(io_fd, &domctl.u.ext_vcpucontext, 128) ||
  41.159 +             (domctl.u.ext_vcpucontext.vcpu != i) )
  41.160 +        {
  41.161 +            ERROR("Error when reading extended ctxt %d", i);
  41.162 +            goto out;
  41.163 +        }
  41.164 +        domctl.cmd = XEN_DOMCTL_set_ext_vcpucontext;
  41.165 +        domctl.domain = dom;
  41.166 +        frc = xc_domctl(xc_handle, &domctl);
  41.167 +        if ( frc != 0 )
  41.168 +        {
  41.169 +            ERROR("Couldn't set extended vcpu%d info\n", i);
  41.170 +            goto out;
  41.171 +        }
  41.172      }
  41.173  
  41.174      if ( !read_exact(io_fd, shared_info_page, PAGE_SIZE) )
    42.1 --- a/tools/libxc/xc_domain_save.c	Tue Oct 30 11:33:55 2007 -0600
    42.2 +++ b/tools/libxc/xc_domain_save.c	Tue Oct 30 15:34:44 2007 -0600
    42.3 @@ -777,16 +777,18 @@ static xen_pfn_t *map_and_save_p2m_table
    42.4       */
    42.5      {
    42.6          unsigned long signature = ~0UL;
    42.7 -        uint32_t chunk_sz = ((guest_width==8) 
    42.8 -                             ? sizeof(ctxt.x64) 
    42.9 -                             : sizeof(ctxt.x32));
   42.10 -        uint32_t tot_sz   = chunk_sz + 8;
   42.11 -        char chunk_sig[]  = "vcpu";
   42.12 +        uint32_t chunk1_sz = ((guest_width==8) 
   42.13 +                              ? sizeof(ctxt.x64) 
   42.14 +                              : sizeof(ctxt.x32));
   42.15 +        uint32_t chunk2_sz = 0;
   42.16 +        uint32_t tot_sz    = (chunk1_sz + 8) + (chunk2_sz + 8);
   42.17          if ( !write_exact(io_fd, &signature, sizeof(signature)) ||
   42.18 -             !write_exact(io_fd, &tot_sz,    sizeof(tot_sz)) ||
   42.19 -             !write_exact(io_fd, &chunk_sig, 4) ||
   42.20 -             !write_exact(io_fd, &chunk_sz,  sizeof(chunk_sz)) ||
   42.21 -             !write_exact(io_fd, &ctxt,      chunk_sz) )
   42.22 +             !write_exact(io_fd, &tot_sz, sizeof(tot_sz)) ||
   42.23 +             !write_exact(io_fd, "vcpu", 4) ||
   42.24 +             !write_exact(io_fd, &chunk1_sz, sizeof(chunk1_sz)) ||
   42.25 +             !write_exact(io_fd, &ctxt, chunk1_sz) ||
   42.26 +             !write_exact(io_fd, "extv", 4) ||
   42.27 +             !write_exact(io_fd, &chunk2_sz, sizeof(chunk2_sz)) )
   42.28          {
   42.29              ERROR("write: extended info");
   42.30              goto out;
   42.31 @@ -830,6 +832,7 @@ int xc_domain_save(int xc_handle, int io
   42.32                     void (*qemu_flip_buffer)(int, int))
   42.33  {
   42.34      xc_dominfo_t info;
   42.35 +    DECLARE_DOMCTL;
   42.36  
   42.37      int rc = 1, frc, i, j, last_iter, iter = 0;
   42.38      int live  = (flags & XCFLAGS_LIVE);
   42.39 @@ -1095,7 +1098,6 @@ int xc_domain_save(int xc_handle, int io
   42.40          while ( N < p2m_size )
   42.41          {
   42.42              unsigned int this_pc = (N * 100) / p2m_size;
   42.43 -            int rc;
   42.44  
   42.45              if ( (this_pc - prev_pc) >= 5 )
   42.46              {
   42.47 @@ -1107,10 +1109,10 @@ int xc_domain_save(int xc_handle, int io
   42.48              {
   42.49                  /* Slightly wasteful to peek the whole array evey time,
   42.50                     but this is fast enough for the moment. */
   42.51 -                rc = xc_shadow_control(
   42.52 +                frc = xc_shadow_control(
   42.53                      xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, 
   42.54                      p2m_size, NULL, 0, NULL);
   42.55 -                if ( rc != p2m_size )
   42.56 +                if ( frc != p2m_size )
   42.57                  {
   42.58                      ERROR("Error peeking shadow bitmap");
   42.59                      goto out;
   42.60 @@ -1601,6 +1603,20 @@ int xc_domain_save(int xc_handle, int io
   42.61              ERROR("Error when writing to state file (1) (errno %d)", errno);
   42.62              goto out;
   42.63          }
   42.64 +
   42.65 +        domctl.cmd = XEN_DOMCTL_get_ext_vcpucontext;
   42.66 +        domctl.domain = dom;
   42.67 +        domctl.u.ext_vcpucontext.vcpu = i;
   42.68 +        if ( xc_domctl(xc_handle, &domctl) < 0 )
   42.69 +        {
   42.70 +            ERROR("No extended context for VCPU%d", i);
   42.71 +            goto out;
   42.72 +        }
   42.73 +        if ( !write_exact(io_fd, &domctl.u.ext_vcpucontext, 128) )
   42.74 +        {
   42.75 +            ERROR("Error when writing to state file (2) (errno %d)", errno);
   42.76 +            goto out;
   42.77 +        }
   42.78      }
   42.79  
   42.80      /*
    43.1 --- a/tools/libxc/xc_misc.c	Tue Oct 30 11:33:55 2007 -0600
    43.2 +++ b/tools/libxc/xc_misc.c	Tue Oct 30 15:34:44 2007 -0600
    43.3 @@ -10,7 +10,7 @@
    43.4  int xc_readconsolering(int xc_handle,
    43.5                         char **pbuffer,
    43.6                         unsigned int *pnr_chars,
    43.7 -                       int clear)
    43.8 +                       int clear, int incremental, uint32_t *pindex)
    43.9  {
   43.10      int ret;
   43.11      DECLARE_SYSCTL;
   43.12 @@ -19,14 +19,24 @@ int xc_readconsolering(int xc_handle,
   43.13  
   43.14      sysctl.cmd = XEN_SYSCTL_readconsole;
   43.15      set_xen_guest_handle(sysctl.u.readconsole.buffer, buffer);
   43.16 -    sysctl.u.readconsole.count  = nr_chars;
   43.17 -    sysctl.u.readconsole.clear  = clear;
   43.18 +    sysctl.u.readconsole.count = nr_chars;
   43.19 +    sysctl.u.readconsole.clear = clear;
   43.20 +    sysctl.u.readconsole.incremental = 0;
   43.21 +    if ( pindex )
   43.22 +    {
   43.23 +        sysctl.u.readconsole.index = *pindex;
   43.24 +        sysctl.u.readconsole.incremental = incremental;
   43.25 +    }
   43.26  
   43.27      if ( (ret = lock_pages(buffer, nr_chars)) != 0 )
   43.28          return ret;
   43.29  
   43.30      if ( (ret = do_sysctl(xc_handle, &sysctl)) == 0 )
   43.31 +    {
   43.32          *pnr_chars = sysctl.u.readconsole.count;
   43.33 +        if ( pindex )
   43.34 +            *pindex = sysctl.u.readconsole.index;
   43.35 +    }
   43.36  
   43.37      unlock_pages(buffer, nr_chars);
   43.38  
    44.1 --- a/tools/libxc/xenctrl.h	Tue Oct 30 11:33:55 2007 -0600
    44.2 +++ b/tools/libxc/xenctrl.h	Tue Oct 30 15:34:44 2007 -0600
    44.3 @@ -549,7 +549,7 @@ int xc_physdev_pci_access_modify(int xc_
    44.4  int xc_readconsolering(int xc_handle,
    44.5                         char **pbuffer,
    44.6                         unsigned int *pnr_chars,
    44.7 -                       int clear);
    44.8 +                       int clear, int incremental, uint32_t *pindex);
    44.9  
   44.10  int xc_send_debug_keys(int xc_handle, char *keys);
   44.11  
   44.12 @@ -616,9 +616,9 @@ int xc_domain_iomem_permission(int xc_ha
   44.13  
   44.14  int xc_domain_pin_memory_cacheattr(int xc_handle,
   44.15                                     uint32_t domid,
   44.16 -                                   unsigned long start,
   44.17 -                                   unsigned long end,
   44.18 -                                   unsigned int type);
   44.19 +                                   uint64_t start,
   44.20 +                                   uint64_t end,
   44.21 +                                   uint32_t type);
   44.22  
   44.23  unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
   44.24                                      unsigned long mfn);
    45.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Tue Oct 30 11:33:55 2007 -0600
    45.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Tue Oct 30 15:34:44 2007 -0600
    45.3 @@ -716,17 +716,19 @@ static PyObject *pyxc_readconsolering(Xc
    45.4                                        PyObject *args,
    45.5                                        PyObject *kwds)
    45.6  {
    45.7 -    unsigned int clear = 0;
    45.8 +    unsigned int clear = 0, index = 0, incremental = 0;
    45.9      char         _str[32768], *str = _str;
   45.10      unsigned int count = 32768;
   45.11      int          ret;
   45.12  
   45.13 -    static char *kwd_list[] = { "clear", NULL };
   45.14 +    static char *kwd_list[] = { "clear", "index", "incremental", NULL };
   45.15  
   45.16 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
   45.17 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwd_list,
   45.18 +                                      &clear, &index, &incremental) )
   45.19          return NULL;
   45.20  
   45.21 -    ret = xc_readconsolering(self->xc_handle, &str, &count, clear);
   45.22 +    ret = xc_readconsolering(self->xc_handle, &str, &count, clear,
   45.23 +                             incremental, &index);
   45.24      if ( ret < 0 )
   45.25          return pyxc_error_to_exception();
   45.26  
    46.1 --- a/tools/python/xen/util/acmpolicy.py	Tue Oct 30 11:33:55 2007 -0600
    46.2 +++ b/tools/python/xen/util/acmpolicy.py	Tue Oct 30 15:34:44 2007 -0600
    46.3 @@ -46,7 +46,7 @@ ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY = 2
    46.4  ACM_POLICY_UNDEFINED = 15
    46.5  
    46.6  
    46.7 -ACM_SCHEMA_FILE = "/etc/xen/acm-security/policies/security_policy.xsd"
    46.8 +ACM_SCHEMA_FILE = ACM_POLICIES_DIR + "security_policy.xsd"
    46.9  
   46.10  ACM_LABEL_UNLABELED = "__UNLABELED__"
   46.11  ACM_LABEL_UNLABELED_DISPLAY = "unlabeled"
   46.12 @@ -263,7 +263,7 @@ class ACMPolicy(XSPolicy):
   46.13          else:
   46.14              #Not loaded in HV
   46.15              self.dom = acmpol_new.dom
   46.16 -            self.compile()
   46.17 +            rc = self.compile()
   46.18          return rc, errors
   46.19  
   46.20  
   46.21 @@ -842,9 +842,15 @@ class ACMPolicy(XSPolicy):
   46.22              rc, mapfile, bin_pol = self.policy_create_map_and_bin()
   46.23  
   46.24              if rc == 0:
   46.25 -                rc = self.__write_to_file(".map", mapfile)
   46.26 -                if rc != 0:
   46.27 -                    log.error("Error writing map file")
   46.28 +                try:
   46.29 +                    security.mapfile_lock()
   46.30 +
   46.31 +                    rc = self.__write_to_file(".map", mapfile)
   46.32 +                    if rc != 0:
   46.33 +                        log.error("Error writing map file")
   46.34 +
   46.35 +                finally:
   46.36 +                    security.mapfile_unlock()
   46.37  
   46.38              if rc == 0:
   46.39                  rc = self.__write_to_file(".bin", bin_pol)
   46.40 @@ -919,7 +925,7 @@ class ACMPolicy(XSPolicy):
   46.41      def policy_get_domain_label_formatted(self, domid):
   46.42          label = self.policy_get_domain_label(domid)
   46.43          if label == "":
   46.44 -            return ""
   46.45 +            label = ACM_LABEL_UNLABELED
   46.46          return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
   46.47  
   46.48      def policy_get_domain_label_by_ssidref_formatted(self, ssidref):
   46.49 @@ -941,6 +947,8 @@ class ACMPolicy(XSPolicy):
   46.50          secpolcode  = ACM_POLICY_UNDEFINED
   46.51          unknown_ste = set()
   46.52          unknown_chw = set()
   46.53 +        unlabeled_ste = "__NULL_LABEL__"
   46.54 +        unlabeled_chw = "__NULL_LABEL__"
   46.55  
   46.56          rc = self.validate()
   46.57          if rc:
   46.58 @@ -979,6 +987,7 @@ class ACMPolicy(XSPolicy):
   46.59              vms_with_chws.sort()
   46.60  
   46.61          if ACM_LABEL_UNLABELED in vms_with_chws:
   46.62 +            unlabeled_chw = ACM_LABEL_UNLABELED
   46.63              vms_with_chws.remove(ACM_LABEL_UNLABELED) ; # @1
   46.64  
   46.65          vms_with_stes = []
   46.66 @@ -996,6 +1005,7 @@ class ACMPolicy(XSPolicy):
   46.67              vms_with_stes.sort()
   46.68  
   46.69          if ACM_LABEL_UNLABELED in vms_with_stes:
   46.70 +            unlabeled_ste = ACM_LABEL_UNLABELED
   46.71              vms_with_stes.remove(ACM_LABEL_UNLABELED) ; # @2
   46.72  
   46.73          resnames = self.policy_get_resourcelabel_names()
   46.74 @@ -1050,7 +1060,8 @@ class ACMPolicy(XSPolicy):
   46.75  
   46.76          if len(vms_with_chws) > 0:
   46.77              mapfile += \
   46.78 -                 "LABEL->SSID ANY CHWALL __NULL_LABEL__       %x\n" % 0
   46.79 +                 "LABEL->SSID ANY CHWALL %-20s %x\n" % \
   46.80 +                 (unlabeled_chw, 0)
   46.81              i = 0
   46.82              for v in vms_with_chws:
   46.83                  mapfile += \
   46.84 @@ -1061,7 +1072,8 @@ class ACMPolicy(XSPolicy):
   46.85  
   46.86          if len(vms_with_stes) > 0 or len(resnames) > 0:
   46.87              mapfile += \
   46.88 -                 "LABEL->SSID ANY STE    __NULL_LABEL__       %08x\n" % 0
   46.89 +                 "LABEL->SSID ANY STE    %-20s %08x\n" % \
   46.90 +                 (unlabeled_ste, 0)
   46.91              i = 0
   46.92              for v in vms_with_stes:
   46.93                  mapfile += \
   46.94 @@ -1260,9 +1272,11 @@ class ACMPolicy(XSPolicy):
   46.95          if len(unknown_ste) > 0:
   46.96              log.info("The following STEs in VM/res labels were unknown:" \
   46.97                       " %s" % list(unknown_ste))
   46.98 +            rc = -xsconstants.XSERR_BAD_LABEL
   46.99          if len(unknown_chw) > 0:
  46.100              log.info("The following Ch. Wall types in labels were unknown:" \
  46.101                       " %s" % list(unknown_chw))
  46.102 +            rc = -xsconstants.XSERR_BAD_LABEL
  46.103          return rc, mapfile, all_bin.tostring()
  46.104  
  46.105      def get_enforced_binary(self):
    47.1 --- a/tools/python/xen/util/xsm/acm/acm.py	Tue Oct 30 11:33:55 2007 -0600
    47.2 +++ b/tools/python/xen/util/xsm/acm/acm.py	Tue Oct 30 15:34:44 2007 -0600
    47.3 @@ -27,6 +27,7 @@ import stat
    47.4  from xen.lowlevel import acm
    47.5  from xen.xend import sxp
    47.6  from xen.xend import XendConstants
    47.7 +from xen.xend import XendOptions
    47.8  from xen.xend.XendLogging import log
    47.9  from xen.xend.XendError import VmError
   47.10  from xen.util import dictio, xsconstants
   47.11 @@ -656,6 +657,10 @@ def get_res_security_details(resource):
   47.12          log.info("Resource label for "+resource+" not in file, using DEFAULT.")
   47.13          return default_security_details()
   47.14  
   47.15 +    if policytype != xsconstants.ACM_POLICY_ID:
   47.16 +        raise VmError("Unknown policy type '%s in label for resource '%s'" %
   47.17 +                      (policytype, resource))
   47.18 +
   47.19      # is this resource label for the running policy?
   47.20      if policy == active_policy:
   47.21          ssidref = label2ssidref(label, policy, 'res')
   47.22 @@ -1077,9 +1082,14 @@ def set_resource_label(resource, policyt
   47.23          if reslabel != "":
   47.24              new_entry = { resource : tuple([policytype, policyref, reslabel])}
   47.25              access_control.update(new_entry)
   47.26 +            command = "add"
   47.27 +            reslbl = ":".join([policytype, policyref, reslabel])
   47.28          else:
   47.29              if access_control.has_key(resource):
   47.30                  del access_control[resource]
   47.31 +            command = "remove"
   47.32 +            reslbl = ""
   47.33 +        run_resource_label_change_script(resource, reslbl, command)
   47.34          dictio.dict_write(access_control, "resources", res_label_filename)
   47.35      finally:
   47.36          resfile_unlock()
   47.37 @@ -1269,6 +1279,7 @@ def change_acm_policy(bin_pol, del_array
   47.38                  label = reslabel_map[label]
   47.39              elif label not in polnew_reslabels:
   47.40                  policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
   47.41 +                run_resource_label_change_script(key, "", "remove")
   47.42              # Update entry
   47.43              access_control[key] = \
   47.44                     tuple([ policytype, new_policyname, label ])
   47.45 @@ -1373,11 +1384,24 @@ def get_security_label(self, xspol=None)
   47.46          from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
   47.47          xspol = XSPolicyAdminInstance().get_loaded_policy()
   47.48  
   47.49 -    if domid == 0:
   47.50 -        if xspol:
   47.51 -            label = xspol.policy_get_domain_label_formatted(domid)
   47.52 -        else:
   47.53 -            label = ""
   47.54 +    label = ""
   47.55 +    if xspol:
   47.56 +        label = xspol.policy_get_domain_label_formatted(domid)
   47.57 +    if domid != 0:
   47.58 +        label = self.info.get('security_label', label)
   47.59 +    return label
   47.60 +
   47.61 +def run_resource_label_change_script(resource, label, command):
   47.62 +    script = XendOptions.instance().get_resource_label_change_script()
   47.63 +    if script:
   47.64 +        parms = {
   47.65 +            'resource' : resource,
   47.66 +            'label'    : label,
   47.67 +            'command'  : command,
   47.68 +        }
   47.69 +        log.info("Running resource label change script %s: %s" %
   47.70 +                 (script, parms))
   47.71 +        parms.update(os.environ)
   47.72 +        os.spawnve(os.P_NOWAIT, script[0], script, parms)
   47.73      else:
   47.74 -        label = self.info.get('security_label', '')
   47.75 -    return label
   47.76 +        log.info("No script given for relabeling of resources.")
    48.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Tue Oct 30 11:33:55 2007 -0600
    48.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Tue Oct 30 15:34:44 2007 -0600
    48.3 @@ -6,6 +6,7 @@
    48.4  # this archive for more details.
    48.5  
    48.6  import os
    48.7 +import os.path
    48.8  import re
    48.9  import string
   48.10  import threading
   48.11 @@ -108,7 +109,7 @@ def save(fd, dominfo, network, live, dst
   48.12          forkHelper(cmd, fd, saveInputHandler, False)
   48.13  
   48.14          # put qemu device model state
   48.15 -        if hvm:
   48.16 +        if os.path.exists("/var/lib/xen/qemu-save.%d" % dominfo.getDomid()):
   48.17              write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
   48.18              qemu_fd = os.open("/var/lib/xen/qemu-save.%d" % dominfo.getDomid(),
   48.19                                os.O_RDONLY)
   48.20 @@ -245,6 +246,8 @@ def restore(xd, fd, dominfo = None, paus
   48.21              raise XendError('Could not read console MFN')        
   48.22  
   48.23          # get qemu state and create a tmp file for dm restore
   48.24 +        # Even PV guests may have QEMU stat, but its not currently
   48.25 +        # used so only bother with HVM currently.
   48.26          if is_hvm:
   48.27              qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
   48.28                                          "invalid device model signature read")
    49.1 --- a/tools/python/xen/xend/XendConfig.py	Tue Oct 30 11:33:55 2007 -0600
    49.2 +++ b/tools/python/xen/xend/XendConfig.py	Tue Oct 30 15:34:44 2007 -0600
    49.3 @@ -28,10 +28,12 @@ from xen.xend.XendError import VmError
    49.4  from xen.xend.XendDevices import XendDevices
    49.5  from xen.xend.PrettyPrint import prettyprintstring
    49.6  from xen.xend.XendConstants import DOM_STATE_HALTED
    49.7 +from xen.xend.xenstore.xstransact import xstransact
    49.8  from xen.xend.server.BlktapController import blktap_disk_types
    49.9  from xen.xend.server.netif import randomMAC
   49.10  from xen.util.blkif import blkdev_name_to_number
   49.11  from xen.util import xsconstants
   49.12 +import xen.util.auxbin
   49.13  
   49.14  log = logging.getLogger("xend.XendConfig")
   49.15  log.setLevel(logging.WARN)
   49.16 @@ -126,7 +128,7 @@ XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 
   49.17                          'fda', 'fdb', 'keymap', 'isa', 'localtime', 'monitor', 
   49.18                          'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
   49.19                          'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
   49.20 -                        'vncconsole', 'vncdisplay', 'vnclisten',
   49.21 +                        'vncconsole', 'vncdisplay', 'vnclisten', 'timer_mode',
   49.22                          'vncpasswd', 'vncunused', 'xauthority', 'pci', 'vhpt']
   49.23  
   49.24  # Xen API console 'other_config' keys.
   49.25 @@ -234,8 +236,6 @@ LEGACY_XENSTORE_VM_PARAMS = [
   49.26      'on_xend_stop',
   49.27  ]
   49.28  
   49.29 -DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm'
   49.30 -
   49.31  ##
   49.32  ## Config Choices
   49.33  ##
   49.34 @@ -393,13 +393,14 @@ class XendConfig(dict):
   49.35              self['name_label'] = 'Domain-' + self['uuid']
   49.36  
   49.37      def _platform_sanity_check(self):
   49.38 -        if self.is_hvm():
   49.39 -            if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap():
   49.40 -                self['platform']['keymap'] = XendOptions.instance().get_keymap()
   49.41 +        if 'keymap' not in self['platform'] and XendOptions.instance().get_keymap():
   49.42 +            self['platform']['keymap'] = XendOptions.instance().get_keymap()
   49.43  
   49.44 +        if self.is_hvm() or self.has_rfb():
   49.45              if 'device_model' not in self['platform']:
   49.46 -                self['platform']['device_model'] = DEFAULT_DM
   49.47 +                self['platform']['device_model'] = xen.util.auxbin.pathTo("qemu-dm")
   49.48  
   49.49 +        if self.is_hvm():
   49.50              # Compatibility hack, can go away soon.
   49.51              if 'soundhw' not in self['platform'] and \
   49.52                 self['platform'].get('enable_audio'):
   49.53 @@ -744,16 +745,7 @@ class XendConfig(dict):
   49.54          # coalesce hvm vnc frame buffer with vfb config
   49.55          if self.is_hvm() and int(self['platform'].get('vnc', 0)) != 0:
   49.56              # add vfb device if it isn't there already
   49.57 -            has_rfb = False
   49.58 -            for console_uuid in self['console_refs']:
   49.59 -                if self['devices'][console_uuid][1].get('protocol') == 'rfb':
   49.60 -                    has_rfb = True
   49.61 -                    break
   49.62 -                if self['devices'][console_uuid][0] == 'vfb':
   49.63 -                    has_rfb = True
   49.64 -                    break
   49.65 -
   49.66 -            if not has_rfb:
   49.67 +            if not self.has_rfb():
   49.68                  dev_config = ['vfb']
   49.69                  dev_config.append(['type', 'vnc'])
   49.70                  # copy VNC related params from platform config to vfb dev conf
   49.71 @@ -765,6 +757,14 @@ class XendConfig(dict):
   49.72                  self.device_add('vfb', cfg_sxp = dev_config)
   49.73  
   49.74  
   49.75 +    def has_rfb(self):
   49.76 +        for console_uuid in self['console_refs']:
   49.77 +            if self['devices'][console_uuid][1].get('protocol') == 'rfb':
   49.78 +                return True
   49.79 +            if self['devices'][console_uuid][0] == 'vfb':
   49.80 +                return True
   49.81 +        return False
   49.82 +
   49.83      def _sxp_to_xapi_unsupported(self, sxp_cfg):
   49.84          """Read in an SXP configuration object and populate
   49.85          values are that not related directly supported in
   49.86 @@ -942,36 +942,43 @@ class XendConfig(dict):
   49.87  
   49.88          # Marshall devices (running or from configuration)
   49.89          if not ignore_devices:
   49.90 -            for cls in XendDevices.valid_devices():
   49.91 -                found = False
   49.92 +            txn = xstransact()
   49.93 +            try:
   49.94 +                for cls in XendDevices.valid_devices():
   49.95 +                    found = False
   49.96                  
   49.97 -                # figure if there is a dev controller is valid and running
   49.98 -                if domain and domain.getDomid() != None:
   49.99 -                    try:
  49.100 -                        controller = domain.getDeviceController(cls)
  49.101 -                        configs = controller.configurations()
  49.102 -                        for config in configs:
  49.103 -                            if sxp.name(config) in ('vbd', 'tap'):
  49.104 -                                # The bootable flag is never written to the
  49.105 -                                # store as part of the device config.
  49.106 -                                dev_uuid = sxp.child_value(config, 'uuid')
  49.107 -                                dev_type, dev_cfg = self['devices'][dev_uuid]
  49.108 -                                is_bootable = dev_cfg.get('bootable', 0)
  49.109 -                                config.append(['bootable', int(is_bootable)])
  49.110 +                    # figure if there is a dev controller is valid and running
  49.111 +                    if domain and domain.getDomid() != None:
  49.112 +                        try:
  49.113 +                            controller = domain.getDeviceController(cls)
  49.114 +                            configs = controller.configurations(txn)
  49.115 +                            for config in configs:
  49.116 +                                if sxp.name(config) in ('vbd', 'tap'):
  49.117 +                                    # The bootable flag is never written to the
  49.118 +                                    # store as part of the device config.
  49.119 +                                    dev_uuid = sxp.child_value(config, 'uuid')
  49.120 +                                    dev_type, dev_cfg = self['devices'][dev_uuid]
  49.121 +                                    is_bootable = dev_cfg.get('bootable', 0)
  49.122 +                                    config.append(['bootable', int(is_bootable)])
  49.123 +
  49.124 +                                sxpr.append(['device', config])
  49.125  
  49.126 -                            sxpr.append(['device', config])
  49.127 -
  49.128 -                        found = True
  49.129 -                    except:
  49.130 -                        log.exception("dumping sxp from device controllers")
  49.131 -                        pass
  49.132 +                            found = True
  49.133 +                        except:
  49.134 +                            log.exception("dumping sxp from device controllers")
  49.135 +                            pass
  49.136                      
  49.137 -                # if we didn't find that device, check the existing config
  49.138 -                # for a device in the same class
  49.139 -                if not found:
  49.140 -                    for dev_type, dev_info in self.all_devices_sxpr():
  49.141 -                        if dev_type == cls:
  49.142 -                            sxpr.append(['device', dev_info])
  49.143 +                    # if we didn't find that device, check the existing config
  49.144 +                    # for a device in the same class
  49.145 +                    if not found:
  49.146 +                        for dev_type, dev_info in self.all_devices_sxpr():
  49.147 +                            if dev_type == cls:
  49.148 +                                sxpr.append(['device', dev_info])
  49.149 +
  49.150 +                txn.commit()
  49.151 +            except:
  49.152 +                txn.abort()
  49.153 +                raise
  49.154  
  49.155          return sxpr    
  49.156      
    50.1 --- a/tools/python/xen/xend/XendConstants.py	Tue Oct 30 11:33:55 2007 -0600
    50.2 +++ b/tools/python/xen/xend/XendConstants.py	Tue Oct 30 15:34:44 2007 -0600
    50.3 @@ -46,6 +46,7 @@ HVM_PARAM_BUFIOREQ_PFN = 6
    50.4  HVM_PARAM_NVRAM_FD     = 7
    50.5  HVM_PARAM_VHPT_SIZE    = 8
    50.6  HVM_PARAM_BUFPIOREQ_PFN = 9
    50.7 +HVM_PARAM_TIMER_MODE   = 10
    50.8  
    50.9  restart_modes = [
   50.10      "restart",
    51.1 --- a/tools/python/xen/xend/XendDomain.py	Tue Oct 30 11:33:55 2007 -0600
    51.2 +++ b/tools/python/xen/xend/XendDomain.py	Tue Oct 30 15:34:44 2007 -0600
    51.3 @@ -393,13 +393,22 @@ class XendDomain:
    51.4          @rtype: None
    51.5          """
    51.6  
    51.7 +        txn = xstransact()
    51.8 +        try:
    51.9 +            self._refreshTxn(txn, refresh_shutdown)
   51.10 +            txn.commit()
   51.11 +        except:
   51.12 +            txn.abort()
   51.13 +            raise
   51.14 +
   51.15 +    def _refreshTxn(self, transaction, refresh_shutdown):
   51.16          running = self._running_domains()
   51.17          # Add domains that are not already tracked but running in Xen,
   51.18          # and update domain state for those that are running and tracked.
   51.19          for dom in running:
   51.20              domid = dom['domid']
   51.21              if domid in self.domains:
   51.22 -                self.domains[domid].update(dom, refresh_shutdown)
   51.23 +                self.domains[domid].update(dom, refresh_shutdown, transaction)
   51.24              elif domid not in self.domains and dom['dying'] != 1:
   51.25                  try:
   51.26                      new_dom = XendDomainInfo.recreate(dom, False)
    52.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Oct 30 11:33:55 2007 -0600
    52.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Oct 30 15:34:44 2007 -0600
    52.3 @@ -819,12 +819,15 @@ class XendDomainInfo:
    52.4  
    52.5          self._update_consoles()
    52.6  
    52.7 -    def _update_consoles(self):
    52.8 +    def _update_consoles(self, transaction = None):
    52.9          if self.domid == None or self.domid == 0:
   52.10              return
   52.11  
   52.12          # Update VT100 port if it exists
   52.13 -        self.console_port = self.readDom('console/port')
   52.14 +        if transaction is None:
   52.15 +            self.console_port = self.readDom('console/port')
   52.16 +        else:
   52.17 +            self.console_port = self.readDomTxn(transaction, 'console/port')
   52.18          if self.console_port is not None:
   52.19              serial_consoles = self.info.console_get_all('vt100')
   52.20              if not serial_consoles:
   52.21 @@ -837,7 +840,10 @@ class XendDomainInfo:
   52.22                  
   52.23  
   52.24          # Update VNC port if it exists and write to xenstore
   52.25 -        vnc_port = self.readDom('console/vnc-port')
   52.26 +        if transaction is None:
   52.27 +            vnc_port = self.readDom('console/vnc-port')
   52.28 +        else:
   52.29 +            vnc_port = self.readDomTxn(transaction, 'console/vnc-port')
   52.30          if vnc_port is not None:
   52.31              for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
   52.32                  if dev_type == 'vfb':
   52.33 @@ -872,6 +878,27 @@ class XendDomainInfo:
   52.34      def storeVm(self, *args):
   52.35          return xstransact.Store(self.vmpath, *args)
   52.36  
   52.37 +
   52.38 +    def _readVmTxn(self, transaction,  *args):
   52.39 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.40 +        return transaction.read(*paths)
   52.41 +
   52.42 +    def _writeVmTxn(self, transaction,  *args):
   52.43 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.44 +        return transaction.write(*paths)
   52.45 +
   52.46 +    def _removeVmTxn(self, transaction,  *args):
   52.47 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.48 +        return transaction.remove(*paths)
   52.49 +
   52.50 +    def _gatherVmTxn(self, transaction,  *args):
   52.51 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.52 +        return transaction.gather(paths)
   52.53 +
   52.54 +    def storeVmTxn(self, transaction,  *args):
   52.55 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.56 +        return transaction.store(*paths)
   52.57 +
   52.58      #
   52.59      # Function to update xenstore /dom/*
   52.60      #
   52.61 @@ -891,6 +918,28 @@ class XendDomainInfo:
   52.62      def storeDom(self, *args):
   52.63          return xstransact.Store(self.dompath, *args)
   52.64  
   52.65 +
   52.66 +    def readDomTxn(self, transaction, *args):
   52.67 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.68 +        return transaction.read(*paths)
   52.69 +
   52.70 +    def gatherDomTxn(self, transaction, *args):
   52.71 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.72 +        return transaction.gather(*paths)
   52.73 +
   52.74 +    def _writeDomTxn(self, transaction, *args):
   52.75 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.76 +        return transaction.write(*paths)
   52.77 +
   52.78 +    def _removeDomTxn(self, transaction, *args):
   52.79 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.80 +        return transaction.remove(*paths)
   52.81 +
   52.82 +    def storeDomTxn(self, transaction, *args):
   52.83 +        paths = map(lambda x: self.vmpath + "/" + x, args)
   52.84 +        return transaction.store(*paths)
   52.85 +
   52.86 +
   52.87      def _recreateDom(self):
   52.88          complete(self.dompath, lambda t: self._recreateDomFunc(t))
   52.89  
   52.90 @@ -916,8 +965,15 @@ class XendDomainInfo:
   52.91                  else:
   52.92                      to_store[n] = str(v)
   52.93  
   52.94 +        # Figure out if we need to tell xenconsoled to ignore this guest's
   52.95 +        # console - device model will handle console if it is running
   52.96 +        constype = "ioemu"
   52.97 +        if 'device_model' not in self.info['platform']:
   52.98 +            constype = "xenconsoled"
   52.99 +
  52.100          f('console/port',     self.console_port)
  52.101          f('console/ring-ref', self.console_mfn)
  52.102 +        f('console/type',     constype)
  52.103          f('store/port',       self.store_port)
  52.104          f('store/ring-ref',   self.store_mfn)
  52.105  
  52.106 @@ -1455,10 +1511,16 @@ class XendDomainInfo:
  52.107  
  52.108      def _releaseDevices(self, suspend = False):
  52.109          """Release all domain's devices.  Nothrow guarantee."""
  52.110 -        if suspend and self.image:
  52.111 -            self.image.destroy(suspend)
  52.112 -            return
  52.113 -
  52.114 +        if self.image:
  52.115 +            try:
  52.116 +                log.debug("Destroying device model")
  52.117 +                self.image.destroyDeviceModel()
  52.118 +            except Exception, e:
  52.119 +                log.exception("Device model destroy failed %s" % str(e))
  52.120 +        else:
  52.121 +            log.debug("No device model")
  52.122 +
  52.123 +        log.debug("Releasing devices")
  52.124          t = xstransact("%s/device" % self.dompath)
  52.125          for devclass in XendDevices.valid_devices():
  52.126              for dev in t.list(devclass):
  52.127 @@ -1583,6 +1645,11 @@ class XendDomainInfo:
  52.128  
  52.129          self._recreateDom()
  52.130  
  52.131 +        # Set timer configration of domain
  52.132 +        if hvm:
  52.133 +            xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
  52.134 +                long(self.info["platform"].get("timer_mode")))
  52.135 +
  52.136          # Set maximum number of vcpus in domain
  52.137          xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
  52.138  
  52.139 @@ -1709,11 +1776,6 @@ class XendDomainInfo:
  52.140              bootloader_tidy(self)
  52.141  
  52.142              if self.image:
  52.143 -                try:
  52.144 -                    self.image.destroy()
  52.145 -                except:
  52.146 -                    log.exception(
  52.147 -                        "XendDomainInfo.cleanup: image.destroy() failed.")
  52.148                  self.image = None
  52.149  
  52.150              try:
  52.151 @@ -1761,10 +1823,9 @@ class XendDomainInfo:
  52.152          self.console_mfn = console_mfn
  52.153  
  52.154          self._introduceDomain()
  52.155 -        if self.info.is_hvm():
  52.156 -            self.image = image.create(self, self.info)
  52.157 -            if self.image:
  52.158 -                self.image.createDeviceModel(True)
  52.159 +        self.image = image.create(self, self.info)
  52.160 +        if self.image:
  52.161 +            self.image.createDeviceModel(True)
  52.162          self._storeDomDetails()
  52.163          self._registerWatches()
  52.164          self.refreshShutdown()
  52.165 @@ -1882,8 +1943,8 @@ class XendDomainInfo:
  52.166              ResumeDomain(self.domid)
  52.167          except:
  52.168              log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid)))
  52.169 -        if self.is_hvm():
  52.170 -            self.image.resumeDeviceModel()
  52.171 +        self.image.resumeDeviceModel()
  52.172 +        log.debug("XendDomainInfo.resumeDomain: completed")
  52.173  
  52.174  
  52.175      #
  52.176 @@ -2211,7 +2272,7 @@ class XendDomainInfo:
  52.177                             (" as domain %s" % str(dom.domid)) or ""))
  52.178          
  52.179  
  52.180 -    def update(self, info = None, refresh = True):
  52.181 +    def update(self, info = None, refresh = True, transaction = None):
  52.182          """Update with info from xc.domain_getinfo().
  52.183          """
  52.184          log.trace("XendDomainInfo.update(%s) on domain %s", info,
  52.185 @@ -2234,7 +2295,7 @@ class XendDomainInfo:
  52.186          # TODO: we should eventually get rid of old_dom_states
  52.187  
  52.188          self.info.update_config(info)
  52.189 -        self._update_consoles()
  52.190 +        self._update_consoles(transaction)
  52.191          
  52.192          if refresh:
  52.193              self.refreshShutdown(info)
    53.1 --- a/tools/python/xen/xend/XendOptions.py	Tue Oct 30 11:33:55 2007 -0600
    53.2 +++ b/tools/python/xen/xend/XendOptions.py	Tue Oct 30 15:34:44 2007 -0600
    53.3 @@ -102,6 +102,15 @@ class XendOptions:
    53.4      """Default interface to listen for VNC connections on"""
    53.5      xend_vnc_listen_default = '127.0.0.1'
    53.6  
    53.7 +    """Use of TLS mode in QEMU VNC server"""
    53.8 +    xend_vnc_tls = 0
    53.9 +
   53.10 +    """x509 certificate directory for QEMU VNC server"""
   53.11 +    xend_vnc_x509_cert_dir = "/etc/xen/vnc"
   53.12 +
   53.13 +    """Verify incoming client x509 certs"""
   53.14 +    xend_vnc_x509_verify = 0
   53.15 +
   53.16      """Default session storage path."""
   53.17      xend_domains_path_default = '/var/lib/xend/domains'
   53.18  
   53.19 @@ -278,6 +287,26 @@ class XendOptions:
   53.20      def get_keymap(self):
   53.21          return self.get_config_value('keymap', None)
   53.22  
   53.23 +    def get_resource_label_change_script(self):
   53.24 +        s = self.get_config_value('resource-label-change-script')
   53.25 +        if s:
   53.26 +            result = s.split(" ")
   53.27 +            result[0] = os.path.join(osdep.scripts_dir, result[0])
   53.28 +            return result
   53.29 +        else:
   53.30 +            return None
   53.31 +
   53.32 +
   53.33 +    def get_vnc_tls(self):
   53.34 +        return self.get_config_string('vnc-tls', self.xend_vnc_tls)
   53.35 +
   53.36 +    def get_vnc_x509_cert_dir(self):
   53.37 +        return self.get_config_string('vnc-x509-cert-dir', self.xend_vnc_x509_cert_dir)
   53.38 +
   53.39 +    def get_vnc_x509_verify(self):
   53.40 +        return self.get_config_string('vnc-x509-verify', self.xend_vnc_x509_verify)
   53.41 +
   53.42 +
   53.43  class XendOptionsFile(XendOptions):
   53.44  
   53.45      """Default path to the config file."""
    54.1 --- a/tools/python/xen/xend/XendXSPolicyAdmin.py	Tue Oct 30 11:33:55 2007 -0600
    54.2 +++ b/tools/python/xen/xend/XendXSPolicyAdmin.py	Tue Oct 30 15:34:44 2007 -0600
    54.3 @@ -28,7 +28,6 @@ from xen.util.xspolicy import XSPolicy
    54.4  from xen.util.acmpolicy import ACMPolicy
    54.5  from xen.xend.XendError import SecurityError
    54.6  
    54.7 -XS_MANAGED_POLICIES_FILE = "/etc/xen/acm-security/policies/managed_policies"
    54.8  
    54.9  class XSPolicyAdmin:
   54.10      """ The class that handles the managed policies in the system.
   54.11 @@ -45,28 +44,19 @@ class XSPolicyAdmin:
   54.12                                  on the system (currently '1')
   54.13          """
   54.14          self.maxpolicies = maxpolicies
   54.15 -        try:
   54.16 -            self.policies = dictio.dict_read("managed_policies",
   54.17 -                                             XS_MANAGED_POLICIES_FILE)
   54.18 -        except Exception, e:
   54.19 -            self.policies = {}
   54.20 -
   54.21 +        self.policies = {}
   54.22          self.xsobjs = {}
   54.23 -        for ref, data in self.policies.items():
   54.24 -            name = data[0]
   54.25 -            typ = data[1]
   54.26 -            try:
   54.27 -                if typ == xsconstants.ACM_POLICY_ID:
   54.28 -                    try:
   54.29 -                        self.xsobjs[ref] = ACMPolicy(name=name, ref=ref)
   54.30 -                    except Exception, e:
   54.31 -                        del self.policies[ref]
   54.32 -                else:
   54.33 -                    del self.policies[ref]
   54.34 -            except Exception, e:
   54.35 -                log.error("XSPolicyAdmin: Could not find policy '%s': %s" %
   54.36 -                         (name, str(e)))
   54.37 -                del self.policies[ref]
   54.38 +
   54.39 +        act_pol_name = self.get_hv_loaded_policy_name()
   54.40 +
   54.41 +        ref = uuid.createString()
   54.42 +        try:
   54.43 +            self.xsobjs[ref] = ACMPolicy(name=act_pol_name, ref=ref)
   54.44 +            self.policies[ref] = (act_pol_name, xsconstants.ACM_POLICY_ID)
   54.45 +        except Exception, e:
   54.46 +            log.error("Could not find XML representation of policy '%s': "
   54.47 +                      "%s" % (act_pol_name,e))
   54.48 +
   54.49          log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
   54.50  
   54.51      def isXSEnabled(self):
   54.52 @@ -113,6 +103,7 @@ class XSPolicyAdmin:
   54.53              if rc == 0:
   54.54                  self.rm_bootpolicy()
   54.55                  irc = self.activate_xspolicy(loadedpol, flags)
   54.56 +                # policy is loaded; if setting the boot flag fails it's ok.
   54.57              return (loadedpol, rc, errors)
   54.58  
   54.59          try:
   54.60 @@ -166,9 +157,6 @@ class XSPolicyAdmin:
   54.61                                         xsconstants.ACM_POLICY_ID]) }
   54.62              self.policies.update(new_entry)
   54.63              self.xsobjs[ref]  = acmpol
   54.64 -            dictio.dict_write(self.policies,
   54.65 -                              "managed_policies",
   54.66 -                              XS_MANAGED_POLICIES_FILE)
   54.67          return (acmpol, xsconstants.XSERR_SUCCESS, errors)
   54.68  
   54.69      def make_boot_policy(self, acmpol):
   54.70 @@ -217,9 +205,6 @@ class XSPolicyAdmin:
   54.71              if rc == xsconstants.XSERR_SUCCESS or force:
   54.72                  del self.policies[ref]
   54.73                  del self.xsobjs[ref]
   54.74 -                dictio.dict_write(self.policies,
   54.75 -                                  "managed_policies",
   54.76 -                                  XS_MANAGED_POLICIES_FILE)
   54.77                  rc = xsconstants.XSERR_SUCCESS
   54.78              return rc
   54.79  
    55.1 --- a/tools/python/xen/xend/image.py	Tue Oct 30 11:33:55 2007 -0600
    55.2 +++ b/tools/python/xen/xend/image.py	Tue Oct 30 15:34:44 2007 -0600
    55.3 @@ -17,7 +17,7 @@
    55.4  #============================================================================
    55.5  
    55.6  
    55.7 -import os, string
    55.8 +import os, os.path, string
    55.9  import re
   55.10  import math
   55.11  import time
   55.12 @@ -31,6 +31,7 @@ from xen.xend.XendOptions import instanc
   55.13  from xen.xend.xenstore.xstransact import xstransact
   55.14  from xen.xend.xenstore.xswatch import xswatch
   55.15  from xen.xend import arch
   55.16 +from xen.xend import XendOptions
   55.17  
   55.18  xc = xen.lowlevel.xc.xc()
   55.19  
   55.20 @@ -56,10 +57,9 @@ class ImageHandler:
   55.21      defining in a subclass.
   55.22  
   55.23      The method createDeviceModel() is called to create the domain device
   55.24 -    model if it needs one.  The default is to do nothing.
   55.25 +    model.
   55.26  
   55.27 -    The method destroy() is called when the domain is destroyed.
   55.28 -    The default is to do nothing.
   55.29 +    The method destroyDeviceModel() is called to reap the device model
   55.30      """
   55.31  
   55.32      ostype = None
   55.33 @@ -91,6 +91,15 @@ class ImageHandler:
   55.34                          ("image/cmdline", self.cmdline),
   55.35                          ("image/ramdisk", self.ramdisk))
   55.36  
   55.37 +        self.dmargs = self.parseDeviceModelArgs(vmConfig)
   55.38 +        self.device_model = vmConfig['platform'].get('device_model')
   55.39 +
   55.40 +        self.display = vmConfig['platform'].get('display')
   55.41 +        self.xauthority = vmConfig['platform'].get('xauthority')
   55.42 +        self.vncconsole = vmConfig['platform'].get('vncconsole')
   55.43 +        self.pid = None
   55.44 +
   55.45 +
   55.46  
   55.47      def cleanupBootloading(self):
   55.48          if self.bootloader:
   55.49 @@ -173,25 +182,158 @@ class ImageHandler:
   55.50          """Build the domain. Define in subclass."""
   55.51          raise NotImplementedError()
   55.52  
   55.53 +    # Return a list of cmd line args to the device models based on the
   55.54 +    # xm config file
   55.55 +    def parseDeviceModelArgs(self, vmConfig):
   55.56 +        ret = ["-domain-name", str(self.vm.info['name_label'])]
   55.57 +
   55.58 +        # Find RFB console device, and if it exists, make QEMU enable
   55.59 +        # the VNC console.
   55.60 +        if int(vmConfig['platform'].get('nographic', 0)) != 0:
   55.61 +            # skip vnc init if nographic is set
   55.62 +            ret.append('-nographic')
   55.63 +            return ret
   55.64 +
   55.65 +        vnc_config = {}
   55.66 +        has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
   55.67 +        has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
   55.68 +        for dev_uuid in vmConfig['console_refs']:
   55.69 +            dev_type, dev_info = vmConfig['devices'][dev_uuid]
   55.70 +            if dev_type == 'vfb':
   55.71 +                vnc_config = dev_info.get('other_config', {})
   55.72 +                has_vnc = True
   55.73 +                break
   55.74 +
   55.75 +        keymap = vmConfig['platform'].get("keymap")
   55.76 +        if keymap:
   55.77 +            ret.append("-k")
   55.78 +            ret.append(keymap)
   55.79 +
   55.80 +        if has_vnc:
   55.81 +            if not vnc_config:
   55.82 +                for key in ('vncunused', 'vnclisten', 'vncdisplay',
   55.83 +                            'vncpasswd'):
   55.84 +                    if key in vmConfig['platform']:
   55.85 +                        vnc_config[key] = vmConfig['platform'][key]
   55.86 +            if vnc_config.has_key("vncpasswd"):
   55.87 +                passwd = vnc_config["vncpasswd"]
   55.88 +            else:
   55.89 +                passwd = XendOptions.instance().get_vncpasswd_default()
   55.90 +            vncopts = ""
   55.91 +            if passwd:
   55.92 +                self.vm.storeVm("vncpasswd", passwd)
   55.93 +                vncopts = vncopts + ",password"
   55.94 +                log.debug("Stored a VNC password for vfb access")
   55.95 +            else:
   55.96 +                log.debug("No VNC passwd configured for vfb access")
   55.97 +
   55.98 +            if XendOptions.instance().get_vnc_tls():
   55.99 +                vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir()
  55.100 +                vncx509verify = XendOptions.instance().get_vnc_x509_verify()
  55.101 +
  55.102 +                if not os.path.exists(vncx509certdir):
  55.103 +                    raise VmError("VNC x509 certificate dir %s does not exist" % vncx509certdir)
  55.104 +
  55.105 +                if vncx509verify:
  55.106 +                    vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir
  55.107 +                else:
  55.108 +                    vncopts = vncopts + ",tls,x509=%s" % vncx509certdir
  55.109 +
  55.110 +
  55.111 +            vnclisten = vnc_config.get('vnclisten',
  55.112 +                                       XendOptions.instance().get_vnclisten_address())
  55.113 +            vncdisplay = vnc_config.get('vncdisplay', 0)
  55.114 +            ret.append('-vnc')
  55.115 +            ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts))
  55.116 +
  55.117 +            if vnc_config.get('vncunused', 0):
  55.118 +                ret.append('-vncunused')
  55.119 +
  55.120 +        elif has_sdl:
  55.121 +            # SDL is default in QEMU.
  55.122 +            pass
  55.123 +        else:
  55.124 +            ret.append('-nographic')
  55.125 +
  55.126 +        if int(vmConfig['platform'].get('monitor', 0)) != 0:
  55.127 +            ret = ret + ['-monitor', 'vc']
  55.128 +        return ret
  55.129 +
  55.130 +    def getDeviceModelArgs(self, restore = False):
  55.131 +        args = [self.device_model]
  55.132 +        args = args + ([ "-d",  "%d" % self.vm.getDomid() ])
  55.133 +        args = args + self.dmargs
  55.134 +        return args
  55.135 +
  55.136      def createDeviceModel(self, restore = False):
  55.137 -        """Create device model for the domain (define in subclass if needed)."""
  55.138 -        pass
  55.139 -    
  55.140 +        if self.device_model is None:
  55.141 +            return
  55.142 +        if self.pid:
  55.143 +            return
  55.144 +        # Execute device model.
  55.145 +        #todo: Error handling
  55.146 +        args = self.getDeviceModelArgs(restore)
  55.147 +        env = dict(os.environ)
  55.148 +        if self.display:
  55.149 +            env['DISPLAY'] = self.display
  55.150 +        if self.xauthority:
  55.151 +            env['XAUTHORITY'] = self.xauthority
  55.152 +        if self.vncconsole:
  55.153 +            args = args + ([ "-vncviewer" ])
  55.154 +        log.info("spawning device models: %s %s", self.device_model, args)
  55.155 +        # keep track of pid and spawned options to kill it later
  55.156 +        self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
  55.157 +        self.vm.storeDom("image/device-model-pid", self.pid)
  55.158 +        log.info("device model pid: %d", self.pid)
  55.159 +
  55.160      def saveDeviceModel(self):
  55.161 -        """Save device model for the domain (define in subclass if needed)."""
  55.162 -        pass
  55.163 +        if self.device_model is None:
  55.164 +            return
  55.165 +        # Signal the device model to pause itself and save its state
  55.166 +        xstransact.Store("/local/domain/0/device-model/%i"
  55.167 +                         % self.vm.getDomid(), ('command', 'save'))
  55.168 +        # Wait for confirmation.  Could do this with a watch but we'd
  55.169 +        # still end up spinning here waiting for the watch to fire. 
  55.170 +        state = ''
  55.171 +        count = 0
  55.172 +        while state != 'paused':
  55.173 +            state = xstransact.Read("/local/domain/0/device-model/%i/state"
  55.174 +                                    % self.vm.getDomid())
  55.175 +            time.sleep(0.1)
  55.176 +            count += 1
  55.177 +            if count > 100:
  55.178 +                raise VmError('Timed out waiting for device model to save')
  55.179  
  55.180      def resumeDeviceModel(self):
  55.181 -        """Unpause device model for the domain (define in subclass if needed)."""
  55.182 -        pass
  55.183 -
  55.184 -    def destroy(self):
  55.185 -        """Extra cleanup on domain destroy (define in subclass if needed)."""
  55.186 -        pass
  55.187 -
  55.188 +        if self.device_model is None:
  55.189 +            return
  55.190 +        # Signal the device model to resume activity after pausing to save.
  55.191 +        xstransact.Store("/local/domain/0/device-model/%i"
  55.192 +                         % self.vm.getDomid(), ('command', 'continue'))
  55.193  
  55.194      def recreate(self):
  55.195 -        pass
  55.196 +        if self.device_model is None:
  55.197 +            return
  55.198 +        self.pid = self.vm.gatherDom(('image/device-model-pid', int))
  55.199 +
  55.200 +    def destroyDeviceModel(self):
  55.201 +        if self.device_model is None:
  55.202 +            return
  55.203 +        if self.pid:
  55.204 +            try:
  55.205 +                os.kill(self.pid, signal.SIGKILL)
  55.206 +            except OSError, exn:
  55.207 +                log.exception(exn)
  55.208 +            try:
  55.209 +                os.waitpid(self.pid, 0)
  55.210 +            except OSError, exn:
  55.211 +                # This is expected if Xend has been restarted within the
  55.212 +                # life of this domain.  In this case, we can kill the process,
  55.213 +                # but we can't wait for it because it's not our child.
  55.214 +                pass
  55.215 +            self.pid = None
  55.216 +            state = xstransact.Remove("/local/domain/0/device-model/%i"
  55.217 +                                      % self.vm.getDomid())
  55.218  
  55.219  
  55.220  class LinuxImageHandler(ImageHandler):
  55.221 @@ -229,6 +371,19 @@ class LinuxImageHandler(ImageHandler):
  55.222                                flags          = self.flags,
  55.223                                vhpt           = self.vhpt)
  55.224  
  55.225 +    def parseDeviceModelArgs(self, vmConfig):
  55.226 +        ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
  55.227 +        # Equivalent to old xenconsoled behaviour. Should make
  55.228 +        # it configurable in future
  55.229 +        ret = ret + ["-serial", "pty"]
  55.230 +        return ret
  55.231 +
  55.232 +    def getDeviceModelArgs(self, restore = False):
  55.233 +        args = ImageHandler.getDeviceModelArgs(self, restore)
  55.234 +        args = args + ([ "-M", "xenpv"])
  55.235 +        return args
  55.236 +
  55.237 +
  55.238  class PPC_LinuxImageHandler(LinuxImageHandler):
  55.239  
  55.240      ostype = "linux"
  55.241 @@ -262,15 +417,6 @@ class HVMImageHandler(ImageHandler):
  55.242          if 'hvm' not in info['xen_caps']:
  55.243              raise HVMRequired()
  55.244  
  55.245 -        self.dmargs = self.parseDeviceModelArgs(vmConfig)
  55.246 -        self.device_model = vmConfig['platform'].get('device_model')
  55.247 -        if not self.device_model:
  55.248 -            raise VmError("hvm: missing device model")
  55.249 -        
  55.250 -        self.display = vmConfig['platform'].get('display')
  55.251 -        self.xauthority = vmConfig['platform'].get('xauthority')
  55.252 -        self.vncconsole = vmConfig['platform'].get('vncconsole')
  55.253 -
  55.254          rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
  55.255  
  55.256          self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
  55.257 @@ -278,49 +424,18 @@ class HVMImageHandler(ImageHandler):
  55.258                          ("image/display", self.display))
  55.259          self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
  55.260  
  55.261 -        self.pid = None
  55.262 -
  55.263          self.apic = int(vmConfig['platform'].get('apic', 0))
  55.264          self.acpi = int(vmConfig['platform'].get('acpi', 0))
  55.265 -        
  55.266 -
  55.267 -    def buildDomain(self):
  55.268 -        store_evtchn = self.vm.getStorePort()
  55.269 -
  55.270 -        mem_mb = self.getRequiredInitialReservation() / 1024
  55.271 -
  55.272 -        log.debug("domid          = %d", self.vm.getDomid())
  55.273 -        log.debug("image          = %s", self.kernel)
  55.274 -        log.debug("store_evtchn   = %d", store_evtchn)
  55.275 -        log.debug("memsize        = %d", mem_mb)
  55.276 -        log.debug("vcpus          = %d", self.vm.getVCpuCount())
  55.277 -        log.debug("acpi           = %d", self.acpi)
  55.278 -        log.debug("apic           = %d", self.apic)
  55.279 -
  55.280 -        rc = xc.hvm_build(domid          = self.vm.getDomid(),
  55.281 -                          image          = self.kernel,
  55.282 -                          memsize        = mem_mb,
  55.283 -                          vcpus          = self.vm.getVCpuCount(),
  55.284 -                          acpi           = self.acpi,
  55.285 -                          apic           = self.apic)
  55.286 -
  55.287 -        rc['notes'] = { 'SUSPEND_CANCEL': 1 }
  55.288 -
  55.289 -        rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
  55.290 -                                           HVM_PARAM_STORE_PFN)
  55.291 -        xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
  55.292 -                         store_evtchn)
  55.293 -
  55.294 -        return rc
  55.295  
  55.296      # Return a list of cmd line args to the device models based on the
  55.297      # xm config file
  55.298      def parseDeviceModelArgs(self, vmConfig):
  55.299 +        ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
  55.300 +        ret = ret + ['-vcpus', str(self.vm.getVCpuCount())]
  55.301 +
  55.302          dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
  55.303                     'localtime', 'serial', 'stdvga', 'isa',
  55.304 -                   'acpi', 'usb', 'usbdevice', 'keymap', 'pci' ]
  55.305 -        
  55.306 -        ret = ['-vcpus', str(self.vm.getVCpuCount())]
  55.307 +                   'acpi', 'usb', 'usbdevice', 'pci' ]
  55.308  
  55.309          for a in dmargs:
  55.310              v = vmConfig['platform'].get(a)
  55.311 @@ -349,7 +464,6 @@ class HVMImageHandler(ImageHandler):
  55.312  
  55.313          # Handle disk/network related options
  55.314          mac = None
  55.315 -        ret = ret + ["-domain-name", str(self.vm.info['name_label'])]
  55.316          nics = 0
  55.317          
  55.318          for devuuid in vmConfig['vbd_refs']:
  55.319 @@ -378,130 +492,43 @@ class HVMImageHandler(ImageHandler):
  55.320              ret.append("-net")
  55.321              ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge))
  55.322  
  55.323 -
  55.324 -        #
  55.325 -        # Find RFB console device, and if it exists, make QEMU enable
  55.326 -        # the VNC console.
  55.327 -        #
  55.328 -        if int(vmConfig['platform'].get('nographic', 0)) != 0:
  55.329 -            # skip vnc init if nographic is set
  55.330 -            ret.append('-nographic')
  55.331 -            return ret
  55.332 -
  55.333 -        vnc_config = {}
  55.334 -        has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
  55.335 -        has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
  55.336 -        for dev_uuid in vmConfig['console_refs']:
  55.337 -            dev_type, dev_info = vmConfig['devices'][dev_uuid]
  55.338 -            if dev_type == 'vfb':
  55.339 -                vnc_config = dev_info.get('other_config', {})
  55.340 -                has_vnc = True
  55.341 -                break
  55.342 -
  55.343 -        if has_vnc:
  55.344 -            if not vnc_config:
  55.345 -                for key in ('vncunused', 'vnclisten', 'vncdisplay',
  55.346 -                            'vncpasswd'):
  55.347 -                    if key in vmConfig['platform']:
  55.348 -                        vnc_config[key] = vmConfig['platform'][key]
  55.349 -
  55.350 -            vnclisten = vnc_config.get('vnclisten',
  55.351 -                                       xenopts().get_vnclisten_address())
  55.352 -            vncdisplay = vnc_config.get('vncdisplay', 0)
  55.353 -            ret.append('-vnc')
  55.354 -            ret.append("%s:%d" % (vnclisten, vncdisplay))
  55.355 -            
  55.356 -            if vnc_config.get('vncunused', 0):
  55.357 -                ret.append('-vncunused')
  55.358 -
  55.359 -            # Store vncpassword in xenstore
  55.360 -            vncpasswd = vnc_config.get('vncpasswd')
  55.361 -            if not vncpasswd:
  55.362 -                vncpasswd = xenopts().get_vncpasswd_default()
  55.363 -
  55.364 -            if vncpasswd is None:
  55.365 -                raise VmError('vncpasswd is not setup in vmconfig or '
  55.366 -                              'xend-config.sxp')
  55.367 -
  55.368 -            if vncpasswd != '':
  55.369 -                self.vm.storeVm('vncpasswd', vncpasswd)
  55.370 -        elif has_sdl:
  55.371 -            # SDL is default in QEMU.
  55.372 -            pass
  55.373 -        else:
  55.374 -            ret.append('-nographic')
  55.375 -
  55.376 -        if int(vmConfig['platform'].get('monitor', 0)) != 0:
  55.377 -            ret = ret + ['-monitor', 'vc']
  55.378          return ret
  55.379  
  55.380 -    def createDeviceModel(self, restore = False):
  55.381 -        if self.pid:
  55.382 -            return
  55.383 -        # Execute device model.
  55.384 -        #todo: Error handling
  55.385 -        args = [self.device_model]
  55.386 -        args = args + ([ "-d",  "%d" % self.vm.getDomid() ])
  55.387 -        if arch.type == "ia64":
  55.388 -            args = args + ([ "-m", "%s" %
  55.389 -                             (self.getRequiredInitialReservation() / 1024) ])
  55.390 -        args = args + self.dmargs
  55.391 +    def getDeviceModelArgs(self, restore = False):
  55.392 +        args = ImageHandler.getDeviceModelArgs(self, restore)
  55.393 +        args = args + ([ "-M", "xenfv"])
  55.394          if restore:
  55.395              args = args + ([ "-loadvm", "/var/lib/xen/qemu-save.%d" %
  55.396                               self.vm.getDomid() ])
  55.397 -        env = dict(os.environ)
  55.398 -        if self.display:
  55.399 -            env['DISPLAY'] = self.display
  55.400 -        if self.xauthority:
  55.401 -            env['XAUTHORITY'] = self.xauthority
  55.402 -        if self.vncconsole:
  55.403 -            args = args + ([ "-vncviewer" ])
  55.404 -        log.info("spawning device models: %s %s", self.device_model, args)
  55.405 -        # keep track of pid and spawned options to kill it later
  55.406 -        self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
  55.407 -        self.vm.storeDom("image/device-model-pid", self.pid)
  55.408 -        log.info("device model pid: %d", self.pid)
  55.409 +        return args
  55.410 +
  55.411 +    def buildDomain(self):
  55.412 +        store_evtchn = self.vm.getStorePort()
  55.413 +
  55.414 +        mem_mb = self.getRequiredInitialReservation() / 1024
  55.415 +
  55.416 +        log.debug("domid          = %d", self.vm.getDomid())
  55.417 +        log.debug("image          = %s", self.kernel)
  55.418 +        log.debug("store_evtchn   = %d", store_evtchn)
  55.419 +        log.debug("memsize        = %d", mem_mb)
  55.420 +        log.debug("vcpus          = %d", self.vm.getVCpuCount())
  55.421 +        log.debug("acpi           = %d", self.acpi)
  55.422 +        log.debug("apic           = %d", self.apic)
  55.423  
  55.424 -    def saveDeviceModel(self):
  55.425 -        # Signal the device model to pause itself and save its state
  55.426 -        xstransact.Store("/local/domain/0/device-model/%i"
  55.427 -                         % self.vm.getDomid(), ('command', 'save'))
  55.428 -        # Wait for confirmation.  Could do this with a watch but we'd
  55.429 -        # still end up spinning here waiting for the watch to fire. 
  55.430 -        state = ''
  55.431 -        count = 0
  55.432 -        while state != 'paused':
  55.433 -            state = xstransact.Read("/local/domain/0/device-model/%i/state"
  55.434 -                                    % self.vm.getDomid())
  55.435 -            time.sleep(0.1)
  55.436 -            count += 1
  55.437 -            if count > 100:
  55.438 -                raise VmError('Timed out waiting for device model to save')
  55.439 +        rc = xc.hvm_build(domid          = self.vm.getDomid(),
  55.440 +                          image          = self.kernel,
  55.441 +                          memsize        = mem_mb,
  55.442 +                          vcpus          = self.vm.getVCpuCount(),
  55.443 +                          acpi           = self.acpi,
  55.444 +                          apic           = self.apic)
  55.445 +        rc['notes'] = { 'SUSPEND_CANCEL': 1 }
  55.446  
  55.447 -    def resumeDeviceModel(self):
  55.448 -        # Signal the device model to resume activity after pausing to save.
  55.449 -        xstransact.Store("/local/domain/0/device-model/%i"
  55.450 -                         % self.vm.getDomid(), ('command', 'continue'))
  55.451 -
  55.452 -    def recreate(self):
  55.453 -        self.pid = self.vm.gatherDom(('image/device-model-pid', int))
  55.454 +        rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
  55.455 +                                           HVM_PARAM_STORE_PFN)
  55.456 +        xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
  55.457 +                         store_evtchn)
  55.458  
  55.459 -    def destroy(self, suspend = False):
  55.460 -        if self.pid and not suspend:
  55.461 -            try:
  55.462 -                os.kill(self.pid, signal.SIGKILL)
  55.463 -            except OSError, exn:
  55.464 -                log.exception(exn)
  55.465 -            try:
  55.466 -                os.waitpid(self.pid, 0)
  55.467 -            except OSError, exn:
  55.468 -                # This is expected if Xend has been restarted within the
  55.469 -                # life of this domain.  In this case, we can kill the process,
  55.470 -                # but we can't wait for it because it's not our child.
  55.471 -                pass
  55.472 -            self.pid = None
  55.473 -            state = xstransact.Remove("/local/domain/0/device-model/%i"
  55.474 -                                      % self.vm.getDomid())
  55.475 +        return rc
  55.476  
  55.477  
  55.478  class IA64_HVM_ImageHandler(HVMImageHandler):
  55.479 @@ -529,6 +556,13 @@ class IA64_HVM_ImageHandler(HVMImageHand
  55.480          # Explicit shadow memory is not a concept 
  55.481          return 0
  55.482  
  55.483 +    def getDeviceModelArgs(self, restore = False):
  55.484 +        args = HVMImageHandler.getDeviceModelArgs(self, restore)
  55.485 +        args = args + ([ "-m", "%s" %
  55.486 +                         (self.getRequiredInitialReservation() / 1024) ])
  55.487 +        return args
  55.488 +
  55.489 +
  55.490  class IA64_Linux_ImageHandler(LinuxImageHandler):
  55.491  
  55.492      def configure(self, vmConfig):
    56.1 --- a/tools/python/xen/xend/server/ConsoleController.py	Tue Oct 30 11:33:55 2007 -0600
    56.2 +++ b/tools/python/xen/xend/server/ConsoleController.py	Tue Oct 30 15:34:44 2007 -0600
    56.3 @@ -19,9 +19,12 @@ class ConsoleController(DevController):
    56.4          return (self.allocateDeviceID(), back, {})
    56.5  
    56.6  
    56.7 -    def getDeviceConfiguration(self, devid):
    56.8 -        result = DevController.getDeviceConfiguration(self, devid)
    56.9 -        devinfo = self.readBackend(devid, *self.valid_cfg)
   56.10 +    def getDeviceConfiguration(self, devid, transaction = None):
   56.11 +        result = DevController.getDeviceConfiguration(self, devid, transaction)
   56.12 +        if transaction is None:
   56.13 +            devinfo = self.readBackend(devid, *self.valid_cfg)
   56.14 +        else:
   56.15 +            devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg)
   56.16          config = dict(zip(self.valid_cfg, devinfo))
   56.17          config = dict([(key, val) for key, val in config.items()
   56.18                         if val != None])
    57.1 --- a/tools/python/xen/xend/server/DevController.py	Tue Oct 30 11:33:55 2007 -0600
    57.2 +++ b/tools/python/xen/xend/server/DevController.py	Tue Oct 30 15:34:44 2007 -0600
    57.3 @@ -239,15 +239,15 @@ class DevController:
    57.4  
    57.5          self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
    57.6  
    57.7 -    def configurations(self):
    57.8 -        return map(self.configuration, self.deviceIDs())
    57.9 +    def configurations(self, transaction = None):
   57.10 +        return map(lambda x: self.configuration(x, transaction), self.deviceIDs(transaction))
   57.11  
   57.12  
   57.13 -    def configuration(self, devid):
   57.14 +    def configuration(self, devid, transaction = None):
   57.15          """@return an s-expression giving the current configuration of the
   57.16          specified device.  This would be suitable for giving to {@link
   57.17          #createDevice} in order to recreate that device."""
   57.18 -        configDict = self.getDeviceConfiguration(devid)
   57.19 +        configDict = self.getDeviceConfiguration(devid, transaction)
   57.20          sxpr = [self.deviceClass]
   57.21          for key, val in configDict.items():
   57.22              if isinstance(val, (types.ListType, types.TupleType)):
   57.23 @@ -273,13 +273,16 @@ class DevController:
   57.24                                     'id', devid]]
   57.25  
   57.26  
   57.27 -    def getDeviceConfiguration(self, devid):
   57.28 +    def getDeviceConfiguration(self, devid, transaction = None):
   57.29          """Returns the configuration of a device.
   57.30  
   57.31          @note: Similar to L{configuration} except it returns a dict.
   57.32          @return: dict
   57.33          """
   57.34 -        backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
   57.35 +        if transaction is None:
   57.36 +            backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
   57.37 +        else:
   57.38 +            backdomid = transaction.read(self.frontendPath(devid) + "/backend-id")
   57.39          if backdomid is None:
   57.40              raise VmError("Device %s not connected" % devid)
   57.41  
   57.42 @@ -416,14 +419,28 @@ class DevController:
   57.43          else:
   57.44              raise VmError("Device %s not connected" % devid)
   57.45  
   57.46 +    def readBackendTxn(self, transaction, devid, *args):
   57.47 +        frontpath = self.frontendPath(devid)
   57.48 +        backpath = transaction.read(frontpath + "/backend")
   57.49 +        if backpath:
   57.50 +            paths = map(lambda x: backpath + "/" + x, args)
   57.51 +            return transaction.read(*paths)
   57.52 +        else:
   57.53 +            raise VmError("Device %s not connected" % devid)
   57.54 +
   57.55      def readFrontend(self, devid, *args):
   57.56          return xstransact.Read(self.frontendPath(devid), *args)
   57.57  
   57.58 +    def readFrontendTxn(self, transaction, devid, *args):
   57.59 +        paths = map(lambda x: self.frontendPath(devid) + "/" + x, args)
   57.60 +        return transaction.read(*paths)
   57.61 +
   57.62      def deviceIDs(self, transaction = None):
   57.63          """@return The IDs of each of the devices currently configured for
   57.64          this instance's deviceClass.
   57.65          """
   57.66          fe = self.backendRoot()
   57.67 +
   57.68          if transaction:
   57.69              return map(lambda x: int(x.split('/')[-1]), transaction.list(fe))
   57.70          else:
    58.1 --- a/tools/python/xen/xend/server/blkif.py	Tue Oct 30 11:33:55 2007 -0600
    58.2 +++ b/tools/python/xen/xend/server/blkif.py	Tue Oct 30 15:34:44 2007 -0600
    58.3 @@ -124,19 +124,26 @@ class BlkifController(DevController):
    58.4                            (self.deviceClass, devid, config))
    58.5  
    58.6  
    58.7 -    def getDeviceConfiguration(self, devid):
    58.8 +    def getDeviceConfiguration(self, devid, transaction = None):
    58.9          """Returns the configuration of a device.
   58.10  
   58.11          @note: Similar to L{configuration} except it returns a dict.
   58.12          @return: dict
   58.13          """
   58.14 -        config = DevController.getDeviceConfiguration(self, devid)
   58.15 -        devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
   58.16 -                                   'uuid')
   58.17 +        config = DevController.getDeviceConfiguration(self, devid, transaction)
   58.18 +        if transaction is None:
   58.19 +            devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
   58.20 +                                       'uuid')
   58.21 +        else:
   58.22 +            devinfo = self.readBackendTxn(transaction, devid,
   58.23 +                                          'dev', 'type', 'params', 'mode', 'uuid')
   58.24          dev, typ, params, mode, uuid = devinfo
   58.25          
   58.26          if dev:
   58.27 -            dev_type = self.readFrontend(devid, 'device-type')
   58.28 +            if transaction is None:
   58.29 +                dev_type = self.readFrontend(devid, 'device-type')
   58.30 +            else:
   58.31 +                dev_type = self.readFrontendTxn(transaction, devid, 'device-type')
   58.32              if dev_type:
   58.33                  dev += ':' + dev_type
   58.34              config['dev'] = dev
    59.1 --- a/tools/python/xen/xend/server/netif.py	Tue Oct 30 11:33:55 2007 -0600
    59.2 +++ b/tools/python/xen/xend/server/netif.py	Tue Oct 30 15:34:44 2007 -0600
    59.3 @@ -183,17 +183,20 @@ class NetifController(DevController):
    59.4                                "network device")
    59.5  
    59.6  
    59.7 -    def getDeviceConfiguration(self, devid):
    59.8 +    def getDeviceConfiguration(self, devid, transaction = None):
    59.9          """@see DevController.configuration"""
   59.10  
   59.11 -        result = DevController.getDeviceConfiguration(self, devid)
   59.12 +        result = DevController.getDeviceConfiguration(self, devid, transaction)
   59.13  
   59.14          config_path = "device/%s/%d/" % (self.deviceClass, devid)
   59.15          devinfo = ()
   59.16          for x in ( 'script', 'ip', 'bridge', 'mac',
   59.17                     'type', 'vifname', 'rate', 'uuid', 'model', 'accel',
   59.18                     'security_label'):
   59.19 -            y = self.vm._readVm(config_path + x)
   59.20 +            if transaction is None:
   59.21 +                y = self.vm._readVm(config_path + x)
   59.22 +            else:
   59.23 +                y = self.vm._readVmTxn(transaction, config_path + x)
   59.24              devinfo += (y,)
   59.25          (script, ip, bridge, mac, typ, vifname, rate, uuid,
   59.26           model, accel, security_label) = devinfo
    60.1 --- a/tools/python/xen/xend/server/pciif.py	Tue Oct 30 11:33:55 2007 -0600
    60.2 +++ b/tools/python/xen/xend/server/pciif.py	Tue Oct 30 15:34:44 2007 -0600
    60.3 @@ -78,8 +78,8 @@ class PciController(DevController):
    60.4          back['uuid'] = config.get('uuid','')
    60.5          return (0, back, {})
    60.6  
    60.7 -    def getDeviceConfiguration(self, devid):
    60.8 -        result = DevController.getDeviceConfiguration(self, devid)
    60.9 +    def getDeviceConfiguration(self, devid, transaction = None):
   60.10 +        result = DevController.getDeviceConfiguration(self, devid, transaction)
   60.11          num_devs = self.readBackend(devid, 'num_devs')
   60.12          pci_devs = []
   60.13          
    61.1 --- a/tools/python/xen/xend/server/tpmif.py	Tue Oct 30 11:33:55 2007 -0600
    61.2 +++ b/tools/python/xen/xend/server/tpmif.py	Tue Oct 30 15:34:44 2007 -0600
    61.3 @@ -75,9 +75,9 @@ class TPMifController(DevController):
    61.4  
    61.5          return (devid, back, front)
    61.6  
    61.7 -    def getDeviceConfiguration(self, devid):
    61.8 +    def getDeviceConfiguration(self, devid, transaction = None):
    61.9          """Returns the configuration of a device"""
   61.10 -        result = DevController.getDeviceConfiguration(self, devid)
   61.11 +        result = DevController.getDeviceConfiguration(self, devid, transaction)
   61.12  
   61.13          (instance, uuid, type) = \
   61.14                             self.readBackend(devid, 'instance',
    62.1 --- a/tools/python/xen/xend/server/vfbif.py	Tue Oct 30 11:33:55 2007 -0600
    62.2 +++ b/tools/python/xen/xend/server/vfbif.py	Tue Oct 30 15:34:44 2007 -0600
    62.3 @@ -5,14 +5,6 @@ from xen.xend.XendError import VmError
    62.4  import xen.xend
    62.5  import os
    62.6  
    62.7 -def spawn_detached(path, args, env):
    62.8 -    p = os.fork()
    62.9 -    if p == 0:
   62.10 -        os.spawnve(os.P_NOWAIT, path, args, env)
   62.11 -        os._exit(0)
   62.12 -    else:
   62.13 -        os.waitpid(p, 0)
   62.14 -        
   62.15  CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused',
   62.16                    'display', 'xauthority', 'keymap',
   62.17                    'uuid', 'location', 'protocol']
   62.18 @@ -35,73 +27,20 @@ class VfbifController(DevController):
   62.19          return (devid, back, {})
   62.20  
   62.21  
   62.22 -    def getDeviceConfiguration(self, devid):
   62.23 -        result = DevController.getDeviceConfiguration(self, devid)
   62.24 +    def getDeviceConfiguration(self, devid, transaction = None):
   62.25 +        result = DevController.getDeviceConfiguration(self, devid, transaction)
   62.26  
   62.27 -        devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
   62.28 +        if transaction is None:
   62.29 +            devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
   62.30 +        else:
   62.31 +            devinfo = self.readBackendTxn(transaction, devid, *CONFIG_ENTRIES)
   62.32          return dict([(CONFIG_ENTRIES[i], devinfo[i])
   62.33                       for i in range(len(CONFIG_ENTRIES))
   62.34                       if devinfo[i] is not None])
   62.35  
   62.36 -
   62.37 -    def createDevice(self, config):
   62.38 -        DevController.createDevice(self, config)
   62.39 -        if self.vm.info.is_hvm():
   62.40 -            # is HVM, so qemu-dm will handle the vfb.
   62.41 -            return
   62.42 -        
   62.43 -        std_args = [ "--domid", "%d" % self.vm.getDomid(),
   62.44 -                     "--title", self.vm.getName() ]
   62.45 -        t = config.get("type", None)
   62.46 -        if t == "vnc":
   62.47 -            passwd = None
   62.48 -            if config.has_key("vncpasswd"):
   62.49 -                passwd = config["vncpasswd"]
   62.50 -            else:
   62.51 -                passwd = xen.xend.XendOptions.instance().get_vncpasswd_default()
   62.52 -            if passwd:
   62.53 -                self.vm.storeVm("vncpasswd", passwd)
   62.54 -                log.debug("Stored a VNC password for vfb access")
   62.55 -            else:
   62.56 -                log.debug("No VNC passwd configured for vfb access")
   62.57 -
   62.58 -            # Try to start the vnc backend
   62.59 -            args = [xen.util.auxbin.pathTo("xen-vncfb")]
   62.60 -            if config.has_key("vncunused"):
   62.61 -                args += ["--unused"]
   62.62 -            elif config.has_key("vncdisplay"):
   62.63 -                args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))]
   62.64 -            vnclisten = config.get("vnclisten",
   62.65 -                                   xen.xend.XendOptions.instance().get_vnclisten_address())
   62.66 -            args += [ "--listen", vnclisten ]
   62.67 -            if config.has_key("keymap"):
   62.68 -                args += ["-k", "%s" % config["keymap"]]
   62.69 -            else:
   62.70 -                xoptions = xen.xend.XendOptions.instance()
   62.71 -                if xoptions.get_keymap():
   62.72 -                    args += ["-k", "%s" % xoptions.get_keymap()]
   62.73 -
   62.74 -            spawn_detached(args[0], args + std_args, os.environ)
   62.75 -        elif t == "sdl":
   62.76 -            args = [xen.util.auxbin.pathTo("xen-sdlfb")]
   62.77 -            env = dict(os.environ)
   62.78 -            if config.has_key("display"):
   62.79 -                env['DISPLAY'] = config["display"]
   62.80 -            if config.has_key("xauthority"):
   62.81 -                env['XAUTHORITY'] = config["xauthority"]
   62.82 -            spawn_detached(args[0], args + std_args, env)
   62.83 -        else:
   62.84 -            raise VmError('Unknown vfb type %s (%s)' % (t, repr(config)))
   62.85 -
   62.86 -
   62.87      def waitForDevice(self, devid):
   62.88 -        if self.vm.info.get('HVM_boot_policy'):
   62.89 -            log.debug('skip waiting for HVM vfb')
   62.90 -            # is a qemu-dm managed device, don't wait for hotplug for these.
   62.91 -            return
   62.92 -
   62.93 -        DevController.waitForDevice(self, devid)
   62.94 -
   62.95 +        # is a qemu-dm managed device, don't wait for hotplug for these.
   62.96 +        return
   62.97  
   62.98      def reconfigureDevice(self, _, config):
   62.99          """ Only allow appending location information of vnc port into
  62.100 @@ -115,19 +54,16 @@ class VfbifController(DevController):
  62.101          raise VmError('Refusing to reconfigure device vfb:%d' % devid)
  62.102  
  62.103      def destroyDevice(self, devid, force):
  62.104 -        if self.vm.info.get('HVM_boot_policy'):
  62.105 -            # remove the backend xenstore entries for HVM guests no matter
  62.106 -            # what
  62.107 -            DevController.destroyDevice(self, devid, True)
  62.108 -        else:
  62.109 -            DevController.destroyDevice(self, devid, force)
  62.110 +        # remove the backend xenstore entries no matter what
  62.111 +        # because we kill qemu-dm with extreme prejudice
  62.112 +        # not giving it a chance to remove them itself
  62.113 +        DevController.destroyDevice(self, devid, True)
  62.114  
  62.115  
  62.116      def migrate(self, deviceConfig, network, dst, step, domName):
  62.117 -        if self.vm.info.get('HVM_boot_policy'):        
  62.118 -            return 0
  62.119 -        return DevController.migrate(self, deviceConfig, network, dst, step,
  62.120 -                                     domName)
  62.121 +        # Handled by qemu-dm so no action needed
  62.122 +        return 0
  62.123 +
  62.124      
  62.125  class VkbdifController(DevController):
  62.126      """Virtual keyboard controller. Handles all vkbd devices for a domain.
  62.127 @@ -141,22 +77,15 @@ class VkbdifController(DevController):
  62.128          return (devid, back, front)
  62.129  
  62.130      def waitForDevice(self, config):
  62.131 -        if self.vm.info.get('HVM_boot_policy'):
  62.132 -            # is a qemu-dm managed device, don't wait for hotplug for these.
  62.133 -            return
  62.134 -
  62.135 -        DevController.waitForDevice(self, config)
  62.136 +        # is a qemu-dm managed device, don't wait for hotplug for these.
  62.137 +        return
  62.138  
  62.139      def destroyDevice(self, devid, force):
  62.140 -        if self.vm.info.get('HVM_boot_policy'):
  62.141 -            # remove the backend xenstore entries for HVM guests no matter
  62.142 -            # what
  62.143 -            DevController.destroyDevice(self, devid, True)
  62.144 -        else:
  62.145 -            DevController.destroyDevice(self, devid, force)
  62.146 +        # remove the backend xenstore entries no matter what
  62.147 +        # because we kill qemu-dm with extreme prejudice
  62.148 +        # not giving it a chance to remove them itself
  62.149 +        DevController.destroyDevice(self, devid, True)
  62.150  
  62.151      def migrate(self, deviceConfig, network, dst, step, domName):
  62.152 -        if self.vm.info.get('HVM_boot_policy'):        
  62.153 -            return 0
  62.154 -        return DevController.migrate(self, deviceConfig, network, dst, step,
  62.155 -                                     domName)        
  62.156 +        # Handled by qemu-dm so no action needed
  62.157 +        return 0
    63.1 --- a/tools/python/xen/xm/addlabel.py	Tue Oct 30 11:33:55 2007 -0600
    63.2 +++ b/tools/python/xen/xm/addlabel.py	Tue Oct 30 15:34:44 2007 -0600
    63.3 @@ -117,15 +117,18 @@ def add_resource_label(label, resource, 
    63.4                                                            res_xapi,
    63.5                                                            "")
    63.6              except Exception, e:
    63.7 -                security.err("Could not label this resource: %s" % e)
    63.8 +                raise security.XSMError("Could not label this resource: %s" %
    63.9 +                                        str(e))
   63.10          else:
   63.11 -            security.err("'%s' is already labeled with '%s'" % (resource,old))
   63.12 +            raise security.XSMError("'%s' is already labeled with '%s'" %
   63.13 +                                    (resource,old))
   63.14  
   63.15  def add_domain_label(label, configfile, policyref):
   63.16      # sanity checks: make sure this label can be instantiated later on
   63.17      ssidref = security.label2ssidref(label, policyref, 'dom')
   63.18  
   63.19 -    new_label = "access_control = ['policy=%s,label=%s']\n" % (policyref, label)
   63.20 +    new_label = "access_control = ['policy=%s,label=%s']\n" % \
   63.21 +                (policyref, label)
   63.22      if not os.path.isfile(configfile):
   63.23          security.err("Configuration file \'" + configfile + "\' not found.")
   63.24      config_fd = open(configfile, "ra+")
   63.25 @@ -150,14 +153,14 @@ def add_domain_label_xapi(label, domainn
   63.26      try:
   63.27          old_lab = server.xenapi.VM.get_security_label(uuid)
   63.28          rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab)
   63.29 -    except:
   63.30 -        rc = -1
   63.31 +    except Exception, e:
   63.32 +        raise security.XSMError("Could not label the domain: %s" % e)
   63.33      if int(rc) < 0:
   63.34          raise OptionError('Could not label domain.')
   63.35      else:
   63.36          ssidref = int(rc)
   63.37          if ssidref != 0:
   63.38 -            print "Set the label of domain '%s' to '%s'. New ssidref = %08x" % \
   63.39 +            print "Set the label of domain '%s' to '%s'. New ssidref = %08x" %\
   63.40                    (domainname,label,ssidref)
   63.41          else:
   63.42              print "Set the label of dormant domain '%s' to '%s'." % \
    64.1 --- a/tools/python/xen/xm/create.py	Tue Oct 30 11:33:55 2007 -0600
    64.2 +++ b/tools/python/xen/xm/create.py	Tue Oct 30 15:34:44 2007 -0600
    64.3 @@ -194,6 +194,11 @@ gopts.var('pae', val='PAE',
    64.4            fn=set_int, default=1,
    64.5            use="Disable or enable PAE of HVM domain.")
    64.6  
    64.7 +gopts.var('timer_mode', val='TIMER_MODE',
    64.8 +          fn=set_int, default=0,
    64.9 +          use="""Timer mode (0=delay virtual time when ticks are missed;
   64.10 +          1=virtual time is always wallclock time.""")
   64.11 +
   64.12  gopts.var('acpi', val='ACPI',
   64.13            fn=set_int, default=1,
   64.14            use="Disable or enable ACPI of HVM domain.")
   64.15 @@ -724,7 +729,7 @@ def configure_vifs(config_devs, vals):
   64.16  def configure_hvm(config_image, vals):
   64.17      """Create the config for HVM devices.
   64.18      """
   64.19 -    args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
   64.20 +    args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb', 'timer_mode',
   64.21               'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
   64.22               'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
   64.23               'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
   64.24 @@ -1228,7 +1233,7 @@ def config_security_check(config, verbos
   64.25              if verbose:
   64.26                  print "   %s: PERMITTED" % (resource)
   64.27  
   64.28 -        except security.XSMError:
   64.29 +        except security.ACMError:
   64.30              print "   %s: DENIED" % (resource)
   64.31              (poltype, res_label, res_policy) = security.get_res_label(resource)
   64.32              if not res_label:
    65.1 --- a/tools/python/xen/xm/rmlabel.py	Tue Oct 30 11:33:55 2007 -0600
    65.2 +++ b/tools/python/xen/xm/rmlabel.py	Tue Oct 30 15:34:44 2007 -0600
    65.3 @@ -50,9 +50,10 @@ def rm_resource_label(resource):
    65.4                  server.xenapi.XSPolicy.set_resource_label(resource,"",
    65.5                                                            oldlabel)
    65.6              else:
    65.7 -                raise security.ACMError("Resource not labeled")
    65.8 +                raise security.XSMError("Resource not labeled")
    65.9          except Exception, e:
   65.10 -            print "Could not remove label from resource: %s" % e
   65.11 +            raise security.XSMError("Could not remove label "
   65.12 +                                    "from resource: %s" % e)
   65.13          return
   65.14  
   65.15      #build canonical resource name
   65.16 @@ -128,7 +129,7 @@ def rm_domain_label_xapi(domainname):
   65.17          old_lab = server.xenapi.VM.get_security_label(uuid)
   65.18          server.xenapi.VM.set_security_label(uuid, "", old_lab)
   65.19      except Exception, e:
   65.20 -        print('Could not remove label from domain: %s' % e)
   65.21 +        raise security.XSMError('Could not remove label from domain: %s' % e)
   65.22  
   65.23  def rm_vif_label(vmname, idx):
   65.24      if xm_main.serverType != xm_main.SERVER_XEN_API:
   65.25 @@ -142,16 +143,21 @@ def rm_vif_label(vmname, idx):
   65.26          raise OptionError("Bad VIF index.")
   65.27      vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
   65.28      if not vif_ref:
   65.29 -        print "A VIF with this UUID does not exist."
   65.30 +        raise security.XSMError("A VIF with this UUID does not exist.")
   65.31      try:
   65.32          old_lab = server.xenapi.VIF.get_security_label(vif_ref)
   65.33 -        rc = server.xenapi.VIF.set_security_label(vif_ref, "", old_lab)
   65.34 -        if int(rc) != 0:
   65.35 -            print "Could not remove the label from the VIF."
   65.36 +        if old_lab != "":
   65.37 +            rc = server.xenapi.VIF.set_security_label(vif_ref, "", old_lab)
   65.38 +            if int(rc) != 0:
   65.39 +                raise security.XSMError("Could not remove the label from"
   65.40 +                                        " the VIF.")
   65.41 +            else:
   65.42 +                print "Successfully removed the label from the VIF."
   65.43          else:
   65.44 -            print "Successfully removed the label from the VIF."
   65.45 +            raise security.XSMError("VIF is not labeled.")
   65.46      except Exception, e:
   65.47 -        print "Could not remove the label the VIF: %s" % str(e)
   65.48 +        raise security.XSMError("Could not remove the label from the VIF: %s" %
   65.49 +                                str(e))
   65.50  
   65.51  
   65.52  def main (argv):
    66.1 --- a/tools/python/xen/xm/setpolicy.py	Tue Oct 30 11:33:55 2007 -0600
    66.2 +++ b/tools/python/xen/xm/setpolicy.py	Tue Oct 30 15:34:44 2007 -0600
    66.3 @@ -23,6 +23,7 @@ import base64
    66.4  import struct
    66.5  import sys
    66.6  import string
    66.7 +import xen.util.xsm.xsm as security
    66.8  from xen.util import xsconstants
    66.9  from xen.util.acmpolicy import ACMPolicy
   66.10  from xen.xm.opts import OptionError
   66.11 @@ -100,21 +101,22 @@ def setpolicy(policytype, policy_name, f
   66.12                                                                flags,
   66.13                                                                overwrite)
   66.14          except Exception, e:
   66.15 -            print "An error occurred setting the policy: %s" % str(e)
   66.16 -            return
   66.17 +            raise security.XSMError("An error occurred setting the "
   66.18 +                                    "policy: %s" % str(e))
   66.19          xserr = int(policystate['xserr'])
   66.20          if xserr != 0:
   66.21 -            print "An error occurred trying to set the policy: %s" % \
   66.22 +            txt = "An error occurred trying to set the policy: %s." % \
   66.23                    xsconstants.xserr2string(abs(xserr))
   66.24              errors = policystate['errors']
   66.25              if len(errors) > 0:
   66.26 -                print "Hypervisor reported errors:"
   66.27 +                txt += "Hypervisor reported errors:"
   66.28                  err = base64.b64decode(errors)
   66.29                  i = 0
   66.30                  while i + 7 < len(err):
   66.31                      code, data = struct.unpack("!ii", errors[i:i+8])
   66.32 -                    print "(0x%08x, 0x%08x)" % (code, data)
   66.33 +                    txt += "(0x%08x, 0x%08x)" % (code, data)
   66.34                      i += 8
   66.35 +            raise security.XSMError(txt)
   66.36          else:
   66.37              print "Successfully set the new policy."
   66.38  
    67.1 --- a/tools/python/xen/xm/xenapi_create.py	Tue Oct 30 11:33:55 2007 -0600
    67.2 +++ b/tools/python/xen/xm/xenapi_create.py	Tue Oct 30 15:34:44 2007 -0600
    67.3 @@ -818,7 +818,7 @@ class sxp2xml:
    67.4  
    67.5  
    67.6      def extract_platform(self, image, document):
    67.7 -        platform_keys = ['acpi', 'apic', 'pae', 'vhpt']
    67.8 +        platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode']
    67.9  
   67.10          def extract_platform_key(key):
   67.11              platform = document.createElement("platform")
    68.1 --- a/tools/xenfb/Makefile	Tue Oct 30 11:33:55 2007 -0600
    68.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.3 @@ -1,32 +0,0 @@
    68.4 -XEN_ROOT=../..
    68.5 -include $(XEN_ROOT)/tools/Rules.mk
    68.6 -
    68.7 -CFLAGS  += -I$(XEN_LIBXC) -I$(XEN_XENSTORE)
    68.8 -CFLAGS  += -I$(XEN_ROOT)/tools/ioemu
    68.9 -LDFLAGS += -L$(XEN_LIBXC) -L$(XEN_XENSTORE)
   68.10 -
   68.11 -.PHONY: all
   68.12 -all: build
   68.13 -
   68.14 -.PHONY: build
   68.15 -build:
   68.16 -	$(MAKE) vncfb sdlfb
   68.17 -
   68.18 -install: all
   68.19 -	$(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
   68.20 -	$(INSTALL_PROG) vncfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfb
   68.21 -	$(INSTALL_PROG) sdlfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfb
   68.22 -
   68.23 -sdlfb: sdlfb.o xenfb.o
   68.24 -
   68.25 -sdlfb.o: CFLAGS += $(shell sdl-config --cflags)
   68.26 -sdlfb: LDLIBS += $(shell sdl-config --libs) -lxenctrl -lxenstore
   68.27 -
   68.28 -clean:
   68.29 -	$(RM) *.o *~ vncfb sdlfb
   68.30 -
   68.31 -vncfb: vncfb.o xenfb.o
   68.32 -vncfb.o: CFLAGS += $(shell libvncserver-config --cflags)
   68.33 -vncfb: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore
   68.34 -
   68.35 -sdlfb.o xenfb.o vncfb.o: xenfb.h
    69.1 --- a/tools/xenfb/sdlfb.c	Tue Oct 30 11:33:55 2007 -0600
    69.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.3 @@ -1,342 +0,0 @@
    69.4 -#include <SDL.h>
    69.5 -#include <errno.h>
    69.6 -#include <sys/types.h>
    69.7 -#include <sys/select.h>
    69.8 -#include <stdlib.h>
    69.9 -#include <linux/input.h>
   69.10 -#include <getopt.h>
   69.11 -#include <string.h>
   69.12 -#include "xenfb.h"
   69.13 -
   69.14 -struct SDLFBData
   69.15 -{
   69.16 -	SDL_Surface *dst;
   69.17 -	SDL_Surface *src;
   69.18 -};
   69.19 -
   69.20 -/*
   69.21 - * Map from scancode to Linux input layer keycode.  Scancodes are
   69.22 - * hardware-specific.  This map assumes a standard AT or PS/2
   69.23 - * keyboard.
   69.24 - *
   69.25 - * Why use scancodes?  We can't use key symbols, because they don't
   69.26 - * identify keys --- they're what keys are mapped to.  The standard
   69.27 - * German keymap, for instance, maps both KEY_COMMA and KEY_102ND to
   69.28 - * SDLK_LESS.
   69.29 - */
   69.30 -static int keymap[256] = {
   69.31 -	[9] = KEY_ESC,
   69.32 -	[10] = KEY_1,
   69.33 -	[11] = KEY_2,
   69.34 -	[12] = KEY_3,
   69.35 -	[13] = KEY_4,
   69.36 -	[14] = KEY_5,
   69.37 -	[15] = KEY_6,
   69.38 -	[16] = KEY_7,
   69.39 -	[17] = KEY_8,
   69.40 -	[18] = KEY_9,
   69.41 -	[19] = KEY_0,
   69.42 -	[20] = KEY_MINUS,
   69.43 -	[21] = KEY_EQUAL,
   69.44 -	[22] = KEY_BACKSPACE,
   69.45 -	[23] = KEY_TAB,
   69.46 -	[24] = KEY_Q,
   69.47 -	[25] = KEY_W,
   69.48 -	[26] = KEY_E,
   69.49 -	[27] = KEY_R,
   69.50 -	[28] = KEY_T,
   69.51 -	[29] = KEY_Y,
   69.52 -	[30] = KEY_U,
   69.53 -	[31] = KEY_I,
   69.54 -	[32] = KEY_O,
   69.55 -	[33] = KEY_P,
   69.56 -	[34] = KEY_LEFTBRACE,
   69.57 -	[35] = KEY_RIGHTBRACE,
   69.58 -	[36] = KEY_ENTER,
   69.59 -	[37] = KEY_LEFTCTRL,
   69.60 -	[38] = KEY_A,
   69.61 -	[39] = KEY_S,
   69.62 -	[40] = KEY_D,
   69.63 -	[41] = KEY_F,
   69.64 -	[42] = KEY_G,
   69.65 -	[43] = KEY_H,
   69.66 -	[44] = KEY_J,
   69.67 -	[45] = KEY_K,
   69.68 -	[46] = KEY_L,
   69.69 -	[47] = KEY_SEMICOLON,
   69.70 -	[48] = KEY_APOSTROPHE,
   69.71 -	[49] = KEY_GRAVE,
   69.72 -	[50] = KEY_LEFTSHIFT,
   69.73 -	[51] = KEY_BACKSLASH,
   69.74 -	[52] = KEY_Z,
   69.75 -	[53] = KEY_X,
   69.76 -	[54] = KEY_C,
   69.77 -	[55] = KEY_V,
   69.78 -	[56] = KEY_B,
   69.79 -	[57] = KEY_N,
   69.80 -	[58] = KEY_M,
   69.81 -	[59] = KEY_COMMA,
   69.82 -	[60] = KEY_DOT,
   69.83 -	[61] = KEY_SLASH,
   69.84 -	[62] = KEY_RIGHTSHIFT,
   69.85 -	[63] = KEY_KPASTERISK,
   69.86 -	[64] = KEY_LEFTALT,
   69.87 -	[65] = KEY_SPACE,
   69.88 -	[66] = KEY_CAPSLOCK,
   69.89 -	[67] = KEY_F1,
   69.90 -	[68] = KEY_F2,
   69.91 -	[69] = KEY_F3,
   69.92 -	[70] = KEY_F4,
   69.93 -	[71] = KEY_F5,
   69.94 -	[72] = KEY_F6,
   69.95 -	[73] = KEY_F7,
   69.96 -	[74] = KEY_F8,
   69.97 -	[75] = KEY_F9,
   69.98 -	[76] = KEY_F10,
   69.99 -	[77] = KEY_NUMLOCK,
  69.100 -	[78] = KEY_SCROLLLOCK,
  69.101 -	[79] = KEY_KP7,
  69.102 -	[80] = KEY_KP8,
  69.103 -	[81] = KEY_KP9,
  69.104 -	[82] = KEY_KPMINUS,
  69.105 -	[83] = KEY_KP4,
  69.106 -	[84] = KEY_KP5,
  69.107 -	[85] = KEY_KP6,
  69.108 -	[86] = KEY_KPPLUS,
  69.109 -	[87] = KEY_KP1,
  69.110 -	[88] = KEY_KP2,
  69.111 -	[89] = KEY_KP3,
  69.112 -	[90] = KEY_KP0,
  69.113 -	[91] = KEY_KPDOT,
  69.114 -	[94] = KEY_102ND,	/* FIXME is this correct? */
  69.115 -	[95] = KEY_F11,
  69.116 -	[96] = KEY_F12,
  69.117 -	[108] = KEY_KPENTER,
  69.118 -	[109] = KEY_RIGHTCTRL,
  69.119 -	[112] = KEY_KPSLASH,
  69.120 -	[111] = KEY_SYSRQ,
  69.121 -	[113] = KEY_RIGHTALT,
  69.122 -	[97] = KEY_HOME,
  69.123 -	[98] = KEY_UP,
  69.124 -	[99] = KEY_PAGEUP,
  69.125 -	[100] = KEY_LEFT,
  69.126 -	[102] = KEY_RIGHT,
  69.127 -	[103] = KEY_END,
  69.128 -	[104] = KEY_DOWN,
  69.129 -	[105] = KEY_PAGEDOWN,
  69.130 -	[106] = KEY_INSERT,
  69.131 -	[107] = KEY_DELETE,
  69.132 -	[110] = KEY_PAUSE,
  69.133 -	[115] = KEY_LEFTMETA,
  69.134 -	[116] = KEY_RIGHTMETA,
  69.135 -	[117] = KEY_MENU,
  69.136 -};
  69.137 -
  69.138 -static int btnmap[] = {
  69.139 -	[SDL_BUTTON_LEFT] = BTN_LEFT,
  69.140 -	[SDL_BUTTON_MIDDLE] = BTN_MIDDLE,
  69.141 -	[SDL_BUTTON_RIGHT] = BTN_RIGHT,
  69.142 -	/* FIXME not 100% sure about these: */
  69.143 -	[SDL_BUTTON_WHEELUP] = BTN_FORWARD,
  69.144 -	[SDL_BUTTON_WHEELDOWN] BTN_BACK
  69.145 -};
  69.146 -
  69.147 -static void sdl_update(struct xenfb *xenfb, int x, int y, int width, int height)
  69.148 -{
  69.149 -	struct SDLFBData *data = xenfb->user_data;
  69.150 -	SDL_Rect r = { x, y, width, height };
  69.151 -	SDL_BlitSurface(data->src, &r, data->dst, &r);
  69.152 -	SDL_UpdateRect(data->dst, x, y, width, height);
  69.153 -}
  69.154 -
  69.155 -static int sdl_on_event(struct xenfb *xenfb, SDL_Event *event)
  69.156 -{
  69.157 -	int x, y, ret;
  69.158 -
  69.159 -	switch (event->type) {
  69.160 -	case SDL_KEYDOWN:
  69.161 -	case SDL_KEYUP:
  69.162 -		if (keymap[event->key.keysym.scancode] == 0)
  69.163 -			break;
  69.164 -		ret = xenfb_send_key(xenfb,
  69.165 -				     event->type == SDL_KEYDOWN,
  69.166 -				     keymap[event->key.keysym.scancode]);
  69.167 -		if (ret < 0)
  69.168 -			fprintf(stderr, "Key %d %s lost (%s)\n",
  69.169 -				keymap[event->key.keysym.scancode],
  69.170 -				event->type == SDL_KEYDOWN ? "down" : "up",
  69.171 -				strerror(errno));
  69.172 -		break;
  69.173 -	case SDL_MOUSEMOTION:
  69.174 -		if (xenfb->abs_pointer_wanted) {
  69.175 -			SDL_GetMouseState(&x, &y);
  69.176 -			ret = xenfb_send_position(xenfb, x, y);
  69.177 -		} else {
  69.178 -			SDL_GetRelativeMouseState(&x, &y);
  69.179 -			ret = xenfb_send_motion(xenfb, x, y);
  69.180 -		}
  69.181 -		if (ret < 0)
  69.182 -			fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
  69.183 -				x, y, strerror(errno));
  69.184 -		break;
  69.185 -	case SDL_MOUSEBUTTONDOWN:
  69.186 -	case SDL_MOUSEBUTTONUP:
  69.187 -		if (event->button.button >= sizeof(btnmap) / sizeof(*btnmap))
  69.188 -			break;
  69.189 -		if (btnmap[event->button.button] == 0)
  69.190 -			break;
  69.191 -		ret = xenfb_send_key(xenfb,
  69.192 -				     event->type == SDL_MOUSEBUTTONDOWN,
  69.193 -				     btnmap[event->button.button]);
  69.194 -		if (ret < 0)
  69.195 -			fprintf(stderr, "Button %d %s lost (%s)\n",
  69.196 -				btnmap[event->button.button] - BTN_MOUSE,
  69.197 -				event->type == SDL_MOUSEBUTTONDOWN ? "down" : "up",
  69.198 -				strerror(errno));
  69.199 -		break;
  69.200 -	case SDL_QUIT:
  69.201 -		return 0;
  69.202 -	}
  69.203 -
  69.204 -	return 1;
  69.205 -}
  69.206 -
  69.207 -static struct option options[] = {
  69.208 -	{ "domid", 1, NULL, 'd' },
  69.209 -	{ "title", 1, NULL, 't' },
  69.210 -	{ NULL }
  69.211 -};
  69.212 -
  69.213 -int main(int argc, char **argv)
  69.214 -{
  69.215 -	struct xenfb *xenfb;
  69.216 -	int domid = -1;
  69.217 -        char * title = NULL;
  69.218 -	fd_set readfds;
  69.219 -	int nfds;
  69.220 -	struct SDLFBData data;
  69.221 -	SDL_Rect r;
  69.222 -	struct timeval tv;
  69.223 -	SDL_Event event;
  69.224 -	int do_quit = 0;
  69.225 -	int opt;
  69.226 -	char *endp;
  69.227 -	int retval;
  69.228 -
  69.229 -	while ((opt = getopt_long(argc, argv, "d:t:", options,
  69.230 -				  NULL)) != -1) {
  69.231 -		switch (opt) {
  69.232 -                case 'd':
  69.233 -			domid = strtol(optarg, &endp, 10);
  69.234 -			if (endp == optarg || *endp) {
  69.235 -				fprintf(stderr, "Invalid domain id specified\n");
  69.236 -				exit(1);
  69.237 -			}
  69.238 -			break;
  69.239 -                case 't':
  69.240 -			title = strdup(optarg);
  69.241 -			break;
  69.242 -		case '?':
  69.243 -			exit(1);
  69.244 -                }
  69.245 -        }
  69.246 -        if (optind != argc) {
  69.247 -		fprintf(stderr, "Invalid options!\n");
  69.248 -		exit(1);
  69.249 -        }
  69.250 -        if (domid <= 0) {
  69.251 -		fprintf(stderr, "Domain ID must be specified!\n");
  69.252 -		exit(1);
  69.253 -        }
  69.254 -
  69.255 -	xenfb = xenfb_new();
  69.256 -	if (xenfb == NULL) {
  69.257 -		fprintf(stderr, "Could not create framebuffer (%s)\n",
  69.258 -			strerror(errno));
  69.259 -		exit(1);
  69.260 -        }
  69.261 -
  69.262 -	if (xenfb_attach_dom(xenfb, domid) < 0) {
  69.263 -		fprintf(stderr, "Could not connect to domain (%s)\n",
  69.264 -			strerror(errno));
  69.265 -		exit(1);
  69.266 -        }
  69.267 -
  69.268 -	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
  69.269 -		fprintf(stderr, "Could not initialize SDL\n");
  69.270 -		exit(1);
  69.271 -	}
  69.272 -
  69.273 -	data.dst = SDL_SetVideoMode(xenfb->width, xenfb->height, xenfb->depth,
  69.274 -				    SDL_SWSURFACE);
  69.275 -	if (!data.dst) {
  69.276 -		fprintf(stderr, "SDL_SetVideoMode failed\n");
  69.277 -		exit(1);
  69.278 -	}
  69.279 -
  69.280 -	data.src = SDL_CreateRGBSurfaceFrom(xenfb->pixels,
  69.281 -					    xenfb->width, xenfb->height,
  69.282 -					    xenfb->depth, xenfb->row_stride,
  69.283 -					    0xFF0000, 0xFF00, 0xFF, 0);
  69.284 -
  69.285 -	if (!data.src) {
  69.286 -		fprintf(stderr, "SDL_CreateRGBSurfaceFrom failed\n");
  69.287 -		exit(1);
  69.288 -	}
  69.289 -
  69.290 -        if (title == NULL)
  69.291 -		title = strdup("xen-sdlfb");
  69.292 -        SDL_WM_SetCaption(title, title);
  69.293 -
  69.294 -	r.x = r.y = 0;
  69.295 -	r.w = xenfb->width;
  69.296 -	r.h = xenfb->height;
  69.297 -	SDL_BlitSurface(data.src, &r, data.dst, &r);
  69.298 -	SDL_UpdateRect(data.dst, 0, 0, xenfb->width, xenfb->height);
  69.299 -
  69.300 -	xenfb->update = sdl_update;
  69.301 -	xenfb->user_data = &data;
  69.302 -
  69.303 -	SDL_ShowCursor(0);
  69.304 -
  69.305 -	/*
  69.306 -	 * We need to wait for fds becoming ready or SDL events to
  69.307 -	 * arrive.  We time out the select after 10ms to poll for SDL
  69.308 -	 * events.  Clunky, but works.  Could avoid the clunkiness
  69.309 -	 * with a separate thread.
  69.310 -	 */
  69.311 -	for (;;) {
  69.312 -		FD_ZERO(&readfds);
  69.313 -		nfds = xenfb_select_fds(xenfb, &readfds);
  69.314 -		tv = (struct timeval){0, 10000};
  69.315 -
  69.316 -		if (select(nfds, &readfds, NULL, NULL, &tv) < 0) {
  69.317 -			if (errno == EINTR)
  69.318 -				continue;
  69.319 -			fprintf(stderr,
  69.320 -				"Can't select() on event channel (%s)\n",
  69.321 -				strerror(errno));
  69.322 -			break;
  69.323 -		}
  69.324 -
  69.325 -		while (SDL_PollEvent(&event)) {
  69.326 -			if (!sdl_on_event(xenfb, &event))
  69.327 -				do_quit = 1;
  69.328 -		}
  69.329 -
  69.330 -                if (do_quit)
  69.331 -			break;
  69.332 -
  69.333 -		retval = xenfb_poll(xenfb, &readfds);
  69.334 -		if (retval == -2)
  69.335 -		    xenfb_teardown(xenfb);
  69.336 -		if (retval < 0)
  69.337 -		    break;
  69.338 -	}
  69.339 -
  69.340 -	xenfb_delete(xenfb);
  69.341 -
  69.342 -	SDL_Quit();
  69.343 -
  69.344 -	return 0;
  69.345 -}
    70.1 --- a/tools/xenfb/vncfb.c	Tue Oct 30 11:33:55 2007 -0600
    70.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.3 @@ -1,522 +0,0 @@
    70.4 -#define _GNU_SOURCE
    70.5 -#include <errno.h>
    70.6 -#include <getopt.h>
    70.7 -#include <stdlib.h>
    70.8 -#include <signal.h>
    70.9 -#include <unistd.h>
   70.10 -#include <malloc.h>
   70.11 -#include <rfb/rfb.h>
   70.12 -#include <rfb/keysym.h>
   70.13 -#include <linux/input.h>
   70.14 -#include <xs.h>
   70.15 -#include "xenfb.h"
   70.16 -
   70.17 -/* Grab key translation support routines from qemu directory. */
   70.18 -#define qemu_mallocz(size) calloc(1, (size))
   70.19 -static const char *bios_dir = "/usr/share/xen/qemu";
   70.20 -#include "vnc_keysym.h"
   70.21 -#include "keymaps.c"
   70.22 -
   70.23 -static unsigned char atkbd_set2_keycode[512] = {
   70.24 -
   70.25 -	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
   70.26 -	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
   70.27 -	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
   70.28 -	  0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
   70.29 -	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
   70.30 -	  0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
   70.31 -	  0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
   70.32 -	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
   70.33 -
   70.34 -	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
   70.35 -	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
   70.36 -	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
   70.37 -	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
   70.38 -	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
   70.39 -	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
   70.40 -	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
   70.41 -	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
   70.42 -
   70.43 -};
   70.44 -
   70.45 -static unsigned char atkbd_unxlate_table[128] = {
   70.46 -
   70.47 -	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
   70.48 -	 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
   70.49 -	 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
   70.50 -	 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
   70.51 -	 11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
   70.52 -	114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
   70.53 -	 71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
   70.54 -	 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
   70.55 -
   70.56 -};
   70.57 -
   70.58 -unsigned char keycode_table[512];
   70.59 -
   70.60 -static void *kbd_layout;
   70.61 -uint8_t modifiers_state[256];
   70.62 -
   70.63 -static int btnmap[] = {
   70.64 -	BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
   70.65 -	BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK
   70.66 -};
   70.67 -
   70.68 -static void press_key_shift_down(struct xenfb* xenfb, int down, int scancode)
   70.69 -{
   70.70 -	if (down)
   70.71 -		xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
   70.72 -
   70.73 -	if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
   70.74 -		fprintf(stderr, "Key %d %s lost (%s)\n",
   70.75 -			scancode, "down", strerror(errno));
   70.76 -
   70.77 -	if (!down)
   70.78 -		xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
   70.79 -}
   70.80 -
   70.81 -static void press_key_shift_up(struct xenfb* xenfb, int down, int scancode)
   70.82 -{
   70.83 -	if (down) {
   70.84 -		if (modifiers_state[0x2a])
   70.85 -			xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
   70.86 -		if (modifiers_state[0x36])
   70.87 -			xenfb_send_key(xenfb, 0, keycode_table[0x36]);
   70.88 -	}
   70.89 -
   70.90 -	if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
   70.91 -		fprintf(stderr, "Key %d %s lost (%s)\n",
   70.92 -			scancode, "down", strerror(errno));
   70.93 -
   70.94 -	if (!down) {
   70.95 -		if (modifiers_state[0x2a])
   70.96 -			xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
   70.97 -		if (modifiers_state[0x36])
   70.98 -			xenfb_send_key(xenfb, 1, keycode_table[0x36]);
   70.99 -	}
  70.100 -}
  70.101 -
  70.102 -static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
  70.103 -{
  70.104 -	/*
  70.105 -	 * We need to map to the key's Linux input layer keycode.
  70.106 -	 * Unfortunately, we don't get the key here, only the
  70.107 -	 * rfbKeySym, which is what the key is mapped to.  Mapping
  70.108 -	 * back to the key is impossible in general, even when you
  70.109 -	 * know the keymap.  For instance, the standard German keymap
  70.110 -	 * maps both KEY_COMMA and KEY_102ND to XK_less.  We simply
  70.111 -	 * assume standard US layout.  This sucks.
  70.112 -	 */
  70.113 -	rfbScreenInfoPtr server = cl->screen;
  70.114 -	struct xenfb *xenfb = server->screenData;
  70.115 -	int scancode;
  70.116 -	int shift = 0;
  70.117 -	int shift_keys = 0;
  70.118 -
  70.119 -	if (keycode >= 'A' && keycode <= 'Z') {
  70.120 -		keycode += 'a' - 'A';
  70.121 -		shift = 1;
  70.122 -	}
  70.123 -	else {
  70.124 -		shift = keysymIsShift(kbd_layout, keycode);
  70.125 -	}
  70.126 -	shift_keys = modifiers_state[0x2a] | modifiers_state[0x36];	
  70.127 -
  70.128 -	scancode = keysym2scancode(kbd_layout, keycode);
  70.129 -	if (scancode == 0)
  70.130 -		return;
  70.131 -
  70.132 -	switch(scancode) {
  70.133 -	case 0x2a:			/* Left Shift */
  70.134 -	case 0x36:			/* Right Shift */
  70.135 -	case 0x1d:			/* Left CTRL */
  70.136 -	case 0x9d:			/* Right CTRL */
  70.137 -	case 0x38:			/* Left ALT */
  70.138 -	case 0xb8:			/* Right ALT */
  70.139 -		if (down)
  70.140 -			modifiers_state[scancode] = 1;
  70.141 -		else
  70.142 -			modifiers_state[scancode] = 0;
  70.143 -		xenfb_send_key(xenfb, down, keycode_table[scancode]); 
  70.144 -		return;
  70.145 -	case 0x45:			/* NumLock */
  70.146 -		if (!down)
  70.147 -			modifiers_state[scancode] ^= 1;
  70.148 -		xenfb_send_key(xenfb, down, keycode_table[scancode]);
  70.149 -		return;
  70.150 -	}
  70.151 -
  70.152 -	if (keycodeIsKeypad(kbd_layout, scancode)) {
  70.153 -	/* If the numlock state needs to change then simulate an additional
  70.154 -	   keypress before sending this one.  This will happen if the user
  70.155 -	   toggles numlock away from the VNC window.
  70.156 -	*/
  70.157 -		if (keysymIsNumlock(kbd_layout, keycode)) {
  70.158 -			if (!modifiers_state[0x45]) {
  70.159 -				modifiers_state[0x45] = 1;
  70.160 -				xenfb_send_key(xenfb, 1, keycode_table[0x45]);
  70.161 -				xenfb_send_key(xenfb, 0, keycode_table[0x45]);
  70.162 -			}
  70.163 -		} else {
  70.164 -			if (modifiers_state[0x45]) {
  70.165 -				modifiers_state[0x45] = 0;
  70.166 -				xenfb_send_key(xenfb, 1, keycode_table[0x45]);
  70.167 -				xenfb_send_key(xenfb, 0, keycode_table[0x45]);
  70.168 -			}
  70.169 -		}
  70.170 -	}
  70.171 -
  70.172 -	/* If the shift state needs to change then simulate an additional
  70.173 -	   keypress before sending this one.
  70.174 -	*/
  70.175 -	if (shift && !shift_keys) {
  70.176 -		press_key_shift_down(xenfb, down, scancode);
  70.177 -		return;
  70.178 -	}
  70.179 -	else if (!shift && shift_keys) {
  70.180 -		press_key_shift_up(xenfb, down, scancode);
  70.181 -		return;
  70.182 -	}
  70.183 -
  70.184 -	if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
  70.185 -		fprintf(stderr, "Key %d %s lost (%s)\n",
  70.186 -			scancode, down ? "down" : "up",
  70.187 -			strerror(errno));
  70.188 -}
  70.189 -
  70.190 -static void on_ptr_event(int buttonMask, int x, int y, rfbClientPtr cl)
  70.191 -{
  70.192 -	/* initial pointer state: at (0,0), buttons up */
  70.193 -	static int last_x, last_y, last_button;
  70.194 -	rfbScreenInfoPtr server = cl->screen;
  70.195 -	struct xenfb *xenfb = server->screenData;
  70.196 -	int i, last_down, down, ret;
  70.197 -
  70.198 -	for (i = 0; i < 8; i++) {
  70.199 -		last_down = last_button & (1 << i);
  70.200 -		down = buttonMask & (1 << i);
  70.201 -		if (down == last_down)
  70.202 -			continue;
  70.203 -		if (i >= sizeof(btnmap) / sizeof(*btnmap))
  70.204 -			break;
  70.205 -		if (btnmap[i] == 0)
  70.206 -			break;
  70.207 -		if (xenfb_send_key(xenfb, down != 0, btnmap[i]) < 0)
  70.208 -			fprintf(stderr, "Button %d %s lost (%s)\n",
  70.209 -				i, down ? "down" : "up", strerror(errno));
  70.210 -	}
  70.211 -
  70.212 -	if (x != last_x || y != last_y) {
  70.213 -		if (xenfb->abs_pointer_wanted) 
  70.214 -			ret = xenfb_send_position(xenfb, x, y);
  70.215 -		else
  70.216 -			ret = xenfb_send_motion(xenfb, x - last_x, y - last_y);
  70.217 -		if (ret < 0)
  70.218 -			fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
  70.219 -				x, y, strerror(errno));
  70.220 -	}
  70.221 -
  70.222 -	last_button = buttonMask;
  70.223 -	last_x = x;
  70.224 -	last_y = y;
  70.225 -}
  70.226 -
  70.227 -static void xenstore_write_vncport(struct xs_handle *xsh, int port, int domid)
  70.228 -{
  70.229 -	char *buf, *path;
  70.230 -	char portstr[10];
  70.231 -
  70.232 -	path = xs_get_domain_path(xsh, domid);
  70.233 -	if (path == NULL) {
  70.234 -		fprintf(stderr, "Can't get domain path (%s)\n",
  70.235 -			strerror(errno));
  70.236 -		goto out;
  70.237 -	}
  70.238 -
  70.239 -	if (asprintf(&buf, "%s/console/vnc-port", path) == -1) {
  70.240 -		fprintf(stderr, "Can't make vncport path\n");
  70.241 -		goto out;
  70.242 -	}
  70.243 -
  70.244 -	if (snprintf(portstr, sizeof(portstr), "%d", port) == -1) {
  70.245 -		fprintf(stderr, "Can't make vncport value\n");
  70.246 -		goto out;
  70.247 -	}
  70.248 -
  70.249 -	if (!xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)))
  70.250 -		fprintf(stderr, "Can't set vncport (%s)\n",
  70.251 -			strerror(errno));
  70.252 -
  70.253 - out:
  70.254 -	free(buf);
  70.255 -}
  70.256 -
  70.257 -
  70.258 -static int xenstore_read_vncpasswd(struct xs_handle *xsh, int domid, char *pwbuf, int pwbuflen)
  70.259 -{
  70.260 -	char buf[256], *path, *uuid = NULL, *passwd = NULL;
  70.261 -	unsigned int len, rc = 0;
  70.262 -
  70.263 -	if (xsh == NULL) {
  70.264 -		return -1;
  70.265 -	}
  70.266 -
  70.267 -	path = xs_get_domain_path(xsh, domid);
  70.268 -	if (path == NULL) {
  70.269 -		fprintf(stderr, "xs_get_domain_path() error\n");
  70.270 -		return -1;
  70.271 -	}
  70.272 -
  70.273 -	snprintf(buf, 256, "%s/vm", path);
  70.274 -	uuid = xs_read(xsh, XBT_NULL, buf, &len);
  70.275 -	if (uuid == NULL) {
  70.276 -		fprintf(stderr, "xs_read(): uuid get error\n");
  70.277 -		free(path);
  70.278 -		return -1;
  70.279 -	}
  70.280 -
  70.281 -	snprintf(buf, 256, "%s/vncpasswd", uuid);
  70.282 -	passwd = xs_read(xsh, XBT_NULL, buf, &len);
  70.283 -	if (passwd == NULL) {
  70.284 -		free(uuid);
  70.285 -		free(path);
  70.286 -		return rc;
  70.287 -	}
  70.288 -
  70.289 -	strncpy(pwbuf, passwd, pwbuflen-1);
  70.290 -	pwbuf[pwbuflen-1] = '\0';
  70.291 -
  70.292 -	fprintf(stderr, "Got a VNC password read from XenStore\n");
  70.293 -
  70.294 -	passwd[0] = '\0';
  70.295 -	snprintf(buf, 256, "%s/vncpasswd", uuid);
  70.296 -	if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
  70.297 -		fprintf(stderr, "xs_write() vncpasswd failed\n");
  70.298 -		rc = -1;
  70.299 -	}
  70.300 -
  70.301 -	free(passwd);
  70.302 -	free(uuid);
  70.303 -	free(path);
  70.304 -
  70.305 -	return rc;
  70.306 -}
  70.307 -
  70.308 -static void vnc_update(struct xenfb *xenfb, int x, int y, int w, int h)
  70.309 -{
  70.310 -	rfbScreenInfoPtr server = xenfb->user_data;
  70.311 -	rfbMarkRectAsModified(server, x, y, x + w, y + h);
  70.312 -}
  70.313 -
  70.314 -static struct option options[] = {
  70.315 -	{ "domid", 1, NULL, 'd' },
  70.316 -	{ "vncport", 1, NULL, 'p' },
  70.317 -	{ "title", 1, NULL, 't' },
  70.318 -	{ "unused", 0, NULL, 'u' },
  70.319 -	{ "listen", 1, NULL, 'l' },
  70.320 -	{ "keymap", 1, NULL, 'k' },
  70.321 -	{ NULL }
  70.322 -};
  70.323 -
  70.324 -int main(int argc, char **argv)
  70.325 -{
  70.326 -	rfbScreenInfoPtr server;
  70.327 -	char *fake_argv[7] = { "vncfb", "-rfbport", "5901", 
  70.328 -                               "-desktop", "xen-vncfb", 
  70.329 -                               "-listen", "127.0.0.1" };
  70.330 -	int fake_argc = sizeof(fake_argv) / sizeof(fake_argv[0]);
  70.331 -	int domid = -1, port = -1;
  70.332 -	char *title = NULL;
  70.333 -	char *listen = NULL;
  70.334 -	char *keymap = NULL;
  70.335 -	bool unused = false;
  70.336 -	int opt;
  70.337 -	struct xenfb *xenfb;
  70.338 -	fd_set readfds;
  70.339 -	int nfds;
  70.340 -	char portstr[10];
  70.341 -	char *endp;
  70.342 -	int r;
  70.343 -	struct xs_handle *xsh;
  70.344 -	char vncpasswd[1024];
  70.345 -	int i;
  70.346 -
  70.347 -	vncpasswd[0] = '\0';
  70.348 -
  70.349 -	while ((opt = getopt_long(argc, argv, "d:p:t:uk:", options,
  70.350 -				  NULL)) != -1) {
  70.351 -		switch (opt) {
  70.352 -                case 'd':
  70.353 -			errno = 0;
  70.354 -			domid = strtol(optarg, &endp, 10);
  70.355 -			if (endp == optarg || *endp || errno) {
  70.356 -				fprintf(stderr, "Invalid domain id specified\n");
  70.357 -				exit(1);
  70.358 -			}
  70.359 -			break;
  70.360 -                case 'p':
  70.361 -			errno = 0;
  70.362 -			port = strtol(optarg, &endp, 10);
  70.363 -			if (endp == optarg || *endp || errno) {
  70.364 -				fprintf(stderr, "Invalid port specified\n");
  70.365 -				exit(1);
  70.366 -			}
  70.367 -			break;
  70.368 -                case 't':
  70.369 -			title = strdup(optarg);
  70.370 -			break;
  70.371 -                case 'u':
  70.372 -			unused = true;
  70.373 -			break;
  70.374 -                case 'l':
  70.375 -			listen = strdup(optarg);
  70.376 -			break;
  70.377 -                case 'k':
  70.378 -			keymap = strdup(optarg);
  70.379 -			break;
  70.380 -		case '?':
  70.381 -			exit(1);
  70.382 -                }
  70.383 -        }
  70.384 -        if (optind != argc) {
  70.385 -		fprintf(stderr, "Invalid options!\n");
  70.386 -		exit(1);
  70.387 -        }
  70.388 -        if (domid <= 0) {
  70.389 -		fprintf(stderr, "Domain ID must be specified!\n");
  70.390 -		exit(1);
  70.391 -        }
  70.392 -            
  70.393 -        if (port <= 0)
  70.394 -		port = 5900 + domid;
  70.395 -	if (snprintf(portstr, sizeof(portstr), "%d", port) == -1) {
  70.396 -		fprintf(stderr, "Invalid port specified\n");
  70.397 -		exit(1);
  70.398 -        }
  70.399 -
  70.400 -	if (keymap == NULL){
  70.401 -		keymap = "en-us";
  70.402 -	}
  70.403 -
  70.404 -	kbd_layout = init_keyboard_layout(keymap);
  70.405 -	if( !kbd_layout ){
  70.406 -		fprintf(stderr, "Invalid keyboard_layout\n");
  70.407 -		exit(1);
  70.408 -        }
  70.409 -
  70.410 -	for (i = 0; i < 128; i++) {
  70.411 -		keycode_table[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
  70.412 -		keycode_table[i | 0x80] = 
  70.413 -			atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
  70.414 -	}
  70.415 -
  70.416 -	for (i = 0; i < 256; i++ ) {
  70.417 -		modifiers_state[i] = 0;
  70.418 -	}
  70.419 -
  70.420 -	fake_argv[2] = portstr;
  70.421 -
  70.422 -        if (title != NULL)
  70.423 -		fake_argv[4] = title;
  70.424 -
  70.425 -        if (listen != NULL)
  70.426 -		fake_argv[6] = listen;
  70.427 -
  70.428 -	signal(SIGPIPE, SIG_IGN);
  70.429 -
  70.430 -	xenfb = xenfb_new();
  70.431 -	if (xenfb == NULL) {
  70.432 -		fprintf(stderr, "Could not create framebuffer (%s)\n",
  70.433 -			strerror(errno));
  70.434 -		exit(1);
  70.435 -	}
  70.436 -
  70.437 -	if (xenfb_attach_dom(xenfb, domid) < 0) {
  70.438 -		fprintf(stderr, "Could not connect to domain (%s)\n",
  70.439 -			strerror(errno));
  70.440 -		exit(1);
  70.441 -	}
  70.442 -
  70.443 -	xsh = xs_daemon_open();
  70.444 -	if (xsh == NULL) {
  70.445 -	        fprintf(stderr, "cannot open connection to xenstore\n");
  70.446 -		exit(1);
  70.447 -	}
  70.448 -
  70.449 -
  70.450 -	if (xenstore_read_vncpasswd(xsh, domid, vncpasswd,
  70.451 -				    sizeof(vncpasswd)/sizeof(char)) < 0) {
  70.452 -		fprintf(stderr, "cannot read VNC password from xenstore\n");
  70.453 -		exit(1);
  70.454 -	}
  70.455 -	  
  70.456 -
  70.457 -	server = rfbGetScreen(&fake_argc, fake_argv, 
  70.458 -			      xenfb->width, xenfb->height,
  70.459 -			      8, 3, xenfb->depth / 8);
  70.460 -	if (server == NULL) {
  70.461 -		fprintf(stderr, "Could not create VNC server\n");
  70.462 -		exit(1);
  70.463 -	}
  70.464 -
  70.465 -	xenfb->user_data = server;
  70.466 -	xenfb->update = vnc_update;
  70.467 -
  70.468 -        if (unused)
  70.469 -		server->autoPort = true;
  70.470 -
  70.471 -	if (vncpasswd[0]) {
  70.472 -		char **passwds = malloc(sizeof(char**)*2);
  70.473 -		if (!passwds) {
  70.474 -			fprintf(stderr, "cannot allocate memory (%s)\n",
  70.475 -				strerror(errno));
  70.476 -			exit(1);
  70.477 -		}
  70.478 -		fprintf(stderr, "Registered password\n");
  70.479 -		passwds[0] = vncpasswd;
  70.480 -		passwds[1] = NULL;
  70.481 -
  70.482 -		server->authPasswdData = passwds;
  70.483 -		server->passwordCheck = rfbCheckPasswordByList;
  70.484 -	} else {
  70.485 -		fprintf(stderr, "Running with no password\n");
  70.486 -	}
  70.487 -	server->serverFormat.redShift = 16;
  70.488 -	server->serverFormat.greenShift = 8;
  70.489 -	server->serverFormat.blueShift = 0;
  70.490 -	server->kbdAddEvent = on_kbd_event;
  70.491 -	server->ptrAddEvent = on_ptr_event;
  70.492 -	server->frameBuffer = xenfb->pixels;
  70.493 -	server->screenData = xenfb;
  70.494 -	server->cursor = NULL;
  70.495 -	rfbInitServer(server);
  70.496 -
  70.497 -	rfbRunEventLoop(server, -1, true);
  70.498 -
  70.499 -        xenstore_write_vncport(xsh, server->port, domid);
  70.500 -
  70.501 -	for (;;) {
  70.502 -		FD_ZERO(&readfds);
  70.503 -		nfds = xenfb_select_fds(xenfb, &readfds);
  70.504 -
  70.505 -		if (select(nfds, &readfds, NULL, NULL, NULL) < 0) {
  70.506 -			if (errno == EINTR)
  70.507 -				continue;
  70.508 -			fprintf(stderr,
  70.509 -				"Can't select() on event channel (%s)\n",
  70.510 -				strerror(errno));
  70.511 -			break;
  70.512 -		}
  70.513 -
  70.514 -		r = xenfb_poll(xenfb, &readfds);
  70.515 -		if (r == -2)
  70.516 -		    xenfb_teardown(xenfb);
  70.517 -		if (r < 0)
  70.518 -		    break;
  70.519 -	}
  70.520 -
  70.521 -	rfbScreenCleanup(server);
  70.522 -	xenfb_delete(xenfb);
  70.523 -
  70.524 -	return 0;
  70.525 -}
    71.1 --- a/tools/xenfb/xenfb.c	Tue Oct 30 11:33:55 2007 -0600
    71.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.3 @@ -1,779 +0,0 @@
    71.4 -#include <stdarg.h>
    71.5 -#include <stdlib.h>
    71.6 -#include <sys/types.h>
    71.7 -#include <fcntl.h>
    71.8 -#include <unistd.h>
    71.9 -#include <xenctrl.h>
   71.10 -#include <xen/io/xenbus.h>
   71.11 -#include <xen/io/fbif.h>
   71.12 -#include <xen/io/kbdif.h>
   71.13 -#include <xen/io/protocols.h>
   71.14 -#include <sys/select.h>
   71.15 -#include <stdbool.h>
   71.16 -#include <xen/event_channel.h>
   71.17 -#include <sys/mman.h>
   71.18 -#include <errno.h>
   71.19 -#include <stdio.h>
   71.20 -#include <string.h>
   71.21 -#include <time.h>
   71.22 -#include <xs.h>
   71.23 -
   71.24 -#include "xenfb.h"
   71.25 -
   71.26 -// FIXME defend against malicious frontend?
   71.27 -
   71.28 -struct xenfb_device {
   71.29 -	const char *devicetype;
   71.30 -	char nodename[64];	/* backend xenstore dir */
   71.31 -	char otherend[64];	/* frontend xenstore dir */
   71.32 -	int otherend_id;	/* frontend domid */
   71.33 -	enum xenbus_state state; /* backend state */
   71.34 -	void *page;		/* shared page */
   71.35 -	evtchn_port_t port;
   71.36 -	struct xenfb_private *xenfb;
   71.37 -};
   71.38 -
   71.39 -struct xenfb_private {
   71.40 -	struct xenfb pub;
   71.41 -	int evt_xch;		/* event channel driver handle */
   71.42 -	int xc;			/* hypervisor interface handle */
   71.43 -	struct xs_handle *xsh;	/* xs daemon handle */
   71.44 -	struct xenfb_device fb, kbd;
   71.45 -	size_t fb_len;		/* size of framebuffer */
   71.46 -	char protocol[64];	/* frontend protocol */
   71.47 -};
   71.48 -
   71.49 -static void xenfb_detach_dom(struct xenfb_private *);
   71.50 -
   71.51 -static char *xenfb_path_in_dom(struct xs_handle *xsh,
   71.52 -			       char *buf, size_t size,
   71.53 -			       unsigned domid, const char *fmt, ...)
   71.54 -{
   71.55 -	va_list ap;
   71.56 -	char *domp = xs_get_domain_path(xsh, domid);
   71.57 -	int n;
   71.58 -
   71.59 -        if (domp == NULL)
   71.60 -		return NULL;
   71.61 -
   71.62 -	n = snprintf(buf, size, "%s/", domp);
   71.63 -	free(domp);
   71.64 -	if (n >= size)
   71.65 -		return NULL;
   71.66 -
   71.67 -	va_start(ap, fmt);
   71.68 -	n += vsnprintf(buf + n, size - n, fmt, ap);
   71.69 -	va_end(ap);
   71.70 -	if (n >= size)
   71.71 -		return NULL;
   71.72 -
   71.73 -	return buf;
   71.74 -}
   71.75 -
   71.76 -static int xenfb_xs_scanf1(struct xs_handle *xsh,
   71.77 -			   const char *dir, const char *node,
   71.78 -			   const char *fmt, void *dest)
   71.79 -{
   71.80 -	char buf[1024];
   71.81 -	char *p;
   71.82 -	int ret;
   71.83 -
   71.84 -	if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
   71.85 -		errno = ENOENT;
   71.86 -		return -1;
   71.87 -        }
   71.88 -	p = xs_read(xsh, XBT_NULL, buf, NULL);
   71.89 -	if (!p) {
   71.90 -		errno = ENOENT;
   71.91 -		return -1;
   71.92 -        }
   71.93 -	ret = sscanf(p, fmt, dest);
   71.94 -	free(p);
   71.95 -	if (ret != 1) {
   71.96 -		errno = EDOM;
   71.97 -		return -1;
   71.98 -        }
   71.99 -	return ret;
  71.100 -}
  71.101 -
  71.102 -static int xenfb_xs_printf(struct xs_handle *xsh,
  71.103 -			   const char *dir, const char *node, char *fmt, ...)
  71.104 -{
  71.105 -	va_list ap;
  71.106 -	char key[1024];
  71.107 -	char val[1024];
  71.108 -	int n;
  71.109 -
  71.110 -	if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
  71.111 -		errno = ENOENT;
  71.112 -		return -1;
  71.113 -        }
  71.114 -
  71.115 -	va_start(ap, fmt);
  71.116 -	n = vsnprintf(val, sizeof(val), fmt, ap);
  71.117 -	va_end(ap);
  71.118 -	if (n >= sizeof(val)) {
  71.119 -		errno = ENOSPC; /* close enough */
  71.120 -		return -1;
  71.121 -	}
  71.122 -
  71.123 -	if (!xs_write(xsh, XBT_NULL, key, val, n))
  71.124 -		return -1;
  71.125 -	return 0;
  71.126 -}
  71.127 -
  71.128 -static void xenfb_device_init(struct xenfb_device *dev,
  71.129 -			      const char *type,
  71.130 -			      struct xenfb_private *xenfb)
  71.131 -{
  71.132 -	dev->devicetype = type;
  71.133 -	dev->otherend_id = -1;
  71.134 -	dev->port = -1;
  71.135 -	dev->xenfb = xenfb;
  71.136 -}
  71.137 -
  71.138 -int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
  71.139 -{
  71.140 -	struct xenfb_private *xenfb = dev->xenfb;
  71.141 -
  71.142 -	dev->otherend_id = domid;
  71.143 -
  71.144 -	if (!xenfb_path_in_dom(xenfb->xsh,
  71.145 -			       dev->otherend, sizeof(dev->otherend),
  71.146 -			       domid, "device/%s/0", dev->devicetype)) {
  71.147 -		errno = ENOENT;
  71.148 -		return -1;
  71.149 -	}
  71.150 -	if (!xenfb_path_in_dom(xenfb->xsh,
  71.151 -			       dev->nodename, sizeof(dev->nodename),
  71.152 -			       0, "backend/%s/%d/0", dev->devicetype, domid)) {
  71.153 -		errno = ENOENT;
  71.154 -		return -1;
  71.155 -	}
  71.156 -
  71.157 -	return 0;
  71.158 -}
  71.159 -
  71.160 -struct xenfb *xenfb_new(void)
  71.161 -{
  71.162 -	struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
  71.163 -	int serrno;
  71.164 -
  71.165 -	if (xenfb == NULL)
  71.166 -		return NULL;
  71.167 -
  71.168 -	memset(xenfb, 0, sizeof(*xenfb));
  71.169 -	xenfb->evt_xch = xenfb->xc = -1;
  71.170 -	xenfb_device_init(&xenfb->fb, "vfb", xenfb);
  71.171 -	xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
  71.172 -
  71.173 -	xenfb->evt_xch = xc_evtchn_open();
  71.174 -	if (xenfb->evt_xch == -1)
  71.175 -		goto fail;
  71.176 -
  71.177 -	xenfb->xc = xc_interface_open();
  71.178 -	if (xenfb->xc == -1)
  71.179 -		goto fail;
  71.180 -
  71.181 -	xenfb->xsh = xs_daemon_open();
  71.182 -	if (!xenfb->xsh)
  71.183 -		goto fail;
  71.184 -
  71.185 -	return &xenfb->pub;
  71.186 -
  71.187 - fail:
  71.188 -	serrno = errno;
  71.189 -	xenfb_delete(&xenfb->pub);
  71.190 -	errno = serrno;
  71.191 -	return NULL;
  71.192 -}
  71.193 -
  71.194 -/* Remove the backend area in xenbus since the framebuffer really is
  71.195 -   going away. */
  71.196 -void xenfb_teardown(struct xenfb *xenfb_pub)
  71.197 -{
  71.198 -       struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.199 -
  71.200 -       xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
  71.201 -       xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
  71.202 -}
  71.203 -
  71.204 -
  71.205 -void xenfb_delete(struct xenfb *xenfb_pub)
  71.206 -{
  71.207 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.208 -
  71.209 -	xenfb_detach_dom(xenfb);
  71.210 -	if (xenfb->xc >= 0)
  71.211 -		xc_interface_close(xenfb->xc);
  71.212 -	if (xenfb->evt_xch >= 0)
  71.213 -		xc_evtchn_close(xenfb->evt_xch);
  71.214 -	if (xenfb->xsh)
  71.215 -		xs_daemon_close(xenfb->xsh);
  71.216 -	free(xenfb);
  71.217 -}
  71.218 -
  71.219 -static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
  71.220 -					  const char *dir)
  71.221 -{
  71.222 -	int ret, state;
  71.223 -
  71.224 -	ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
  71.225 -	if (ret < 0)
  71.226 -		return XenbusStateUnknown;
  71.227 -
  71.228 -	if ((unsigned)state > XenbusStateClosed)
  71.229 -		state = XenbusStateUnknown;
  71.230 -	return state;
  71.231 -}
  71.232 -
  71.233 -static int xenfb_switch_state(struct xenfb_device *dev,
  71.234 -			      enum xenbus_state state)
  71.235 -{
  71.236 -	struct xs_handle *xsh = dev->xenfb->xsh;
  71.237 -
  71.238 -	if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
  71.239 -		return -1;
  71.240 -	dev->state = state;
  71.241 -	return 0;
  71.242 -}
  71.243 -
  71.244 -static int xenfb_wait_for_state(struct xs_handle *xsh, const char *dir,
  71.245 -				unsigned awaited)
  71.246 -{
  71.247 -	unsigned state, dummy;
  71.248 -	char **vec;
  71.249 -
  71.250 -	awaited |= 1 << XenbusStateUnknown;
  71.251 -
  71.252 -	for (;;) {
  71.253 -		state = xenfb_read_state(xsh, dir);
  71.254 -		if ((1 << state) & awaited)
  71.255 -			return state;
  71.256 -
  71.257 -		vec = xs_read_watch(xsh, &dummy);
  71.258 -		if (!vec)
  71.259 -			return -1;
  71.260 -		free(vec);
  71.261 -	}
  71.262 -}
  71.263 -
  71.264 -static int xenfb_wait_for_backend_creation(struct xenfb_device *dev)
  71.265 -{
  71.266 -	struct xs_handle *xsh = dev->xenfb->xsh;
  71.267 -	int state;
  71.268 -
  71.269 -	if (!xs_watch(xsh, dev->nodename, ""))
  71.270 -		return -1;
  71.271 -	state = xenfb_wait_for_state(xsh, dev->nodename,
  71.272 -			(1 << XenbusStateInitialising)
  71.273 -			| (1 << XenbusStateClosed)
  71.274 -#if 1 /* TODO fudging state to permit restarting; to be removed */
  71.275 -			| (1 << XenbusStateInitWait)
  71.276 -			| (1 << XenbusStateConnected)
  71.277 -			| (1 << XenbusStateClosing)
  71.278 -#endif
  71.279 -			);
  71.280 -	xs_unwatch(xsh, dev->nodename, "");
  71.281 -
  71.282 -	switch (state) {
  71.283 -#if 1
  71.284 -	case XenbusStateInitWait:
  71.285 -	case XenbusStateConnected:
  71.286 -		printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */
  71.287 -#endif
  71.288 -	case XenbusStateInitialising:
  71.289 -	case XenbusStateClosing:
  71.290 -	case XenbusStateClosed:
  71.291 -		break;
  71.292 -	default:
  71.293 -		return -1;
  71.294 -	}
  71.295 -
  71.296 -	return 0;
  71.297 -}
  71.298 -
  71.299 -static int xenfb_hotplug(struct xenfb_device *dev)
  71.300 -{
  71.301 -	if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
  71.302 -			    "hotplug-status", "connected"))
  71.303 -		return -1;
  71.304 -	return 0;
  71.305 -}
  71.306 -
  71.307 -static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev)
  71.308 -{
  71.309 -	switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
  71.310 -#if 1 /* TODO fudging state to permit restarting; to be removed */
  71.311 -			(1 << XenbusStateInitialised)
  71.312 -			| (1 << XenbusStateConnected)
  71.313 -#else
  71.314 -			1 << XenbusStateInitialised,
  71.315 -#endif
  71.316 -			)) {
  71.317 -#if 1
  71.318 -	case XenbusStateConnected:
  71.319 -		printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */
  71.320 -#endif
  71.321 -	case XenbusStateInitialised:
  71.322 -		break;
  71.323 -	default:
  71.324 -		return -1;
  71.325 -	}
  71.326 -
  71.327 -	return 0;
  71.328 -}
  71.329 -
  71.330 -static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
  71.331 -{
  71.332 -	uint32_t *src32 = src;
  71.333 -	uint64_t *src64 = src;
  71.334 -	int i;
  71.335 -
  71.336 -	for (i = 0; i < count; i++)
  71.337 -		dst[i] = (mode == 32) ? src32[i] : src64[i];
  71.338 -}
  71.339 -
  71.340 -static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
  71.341 -{
  71.342 -	struct xenfb_page *page = xenfb->fb.page;
  71.343 -	int n_fbmfns;
  71.344 -	int n_fbdirs;
  71.345 -	unsigned long *pgmfns = NULL;
  71.346 -	unsigned long *fbmfns = NULL;
  71.347 -	void *map, *pd;
  71.348 -	int mode, ret = -1;
  71.349 -
  71.350 -	/* default to native */
  71.351 -	pd = page->pd;
  71.352 -	mode = sizeof(unsigned long) * 8;
  71.353 -
  71.354 -	if (0 == strlen(xenfb->protocol)) {
  71.355 -		/*
  71.356 -		 * Undefined protocol, some guesswork needed.
  71.357 -		 *
  71.358 -		 * Old frontends which don't set the protocol use
  71.359 -		 * one page directory only, thus pd[1] must be zero.
  71.360 -		 * pd[1] of the 32bit struct layout and the lower
  71.361 -		 * 32 bits of pd[0] of the 64bit struct layout have
  71.362 -		 * the same location, so we can check that ...
  71.363 -		 */
  71.364 -		uint32_t *ptr32 = NULL;
  71.365 -		uint32_t *ptr64 = NULL;
  71.366 -#if defined(__i386__)
  71.367 -		ptr32 = (void*)page->pd;
  71.368 -		ptr64 = ((void*)page->pd) + 4;
  71.369 -#elif defined(__x86_64__)
  71.370 -		ptr32 = ((void*)page->pd) - 4;
  71.371 -		ptr64 = (void*)page->pd;
  71.372 -#endif
  71.373 -		if (ptr32) {
  71.374 -			if (0 == ptr32[1]) {
  71.375 -				mode = 32;
  71.376 -				pd   = ptr32;
  71.377 -			} else {
  71.378 -				mode = 64;
  71.379 -				pd   = ptr64;
  71.380 -			}
  71.381 -		}
  71.382 -#if defined(__x86_64__)
  71.383 -	} else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
  71.384 -		/* 64bit dom0, 32bit domU */
  71.385 -		mode = 32;
  71.386 -		pd   = ((void*)page->pd) - 4;
  71.387 -#elif defined(__i386__)
  71.388 -	} else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
  71.389 -		/* 32bit dom0, 64bit domU */
  71.390 -		mode = 64;
  71.391 -		pd   = ((void*)page->pd) + 4;
  71.392 -#endif
  71.393 -	}
  71.394 -
  71.395 -	n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
  71.396 -	n_fbdirs = n_fbmfns * mode / 8;
  71.397 -	n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
  71.398 -
  71.399 -	pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
  71.400 -	fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
  71.401 -	if (!pgmfns || !fbmfns)
  71.402 -		goto out;
  71.403 -
  71.404 -	xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
  71.405 -	map = xc_map_foreign_pages(xenfb->xc, domid,
  71.406 -				   PROT_READ, pgmfns, n_fbdirs);
  71.407 -	if (map == NULL)
  71.408 -		goto out;
  71.409 -	xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
  71.410 -	munmap(map, n_fbdirs * XC_PAGE_SIZE);
  71.411 -
  71.412 -	xenfb->pub.pixels = xc_map_foreign_pages(xenfb->xc, domid,
  71.413 -				PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
  71.414 -	if (xenfb->pub.pixels == NULL)
  71.415 -		goto out;
  71.416 -
  71.417 -	ret = 0; /* all is fine */
  71.418 -
  71.419 - out:
  71.420 -	if (pgmfns)
  71.421 -		free(pgmfns);
  71.422 -	if (fbmfns)
  71.423 -		free(fbmfns);
  71.424 -	return ret;
  71.425 -}
  71.426 -
  71.427 -static int xenfb_bind(struct xenfb_device *dev)
  71.428 -{
  71.429 -	struct xenfb_private *xenfb = dev->xenfb;
  71.430 -	unsigned long mfn;
  71.431 -	evtchn_port_t evtchn;
  71.432 -
  71.433 -	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
  71.434 -			    &mfn) < 0)
  71.435 -		return -1;
  71.436 -	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
  71.437 -			    &evtchn) < 0)
  71.438 -		return -1;
  71.439 -
  71.440 -	dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
  71.441 -					       dev->otherend_id, evtchn);
  71.442 -	if (dev->port == -1)
  71.443 -		return -1;
  71.444 -
  71.445 -	dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
  71.446 -			XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
  71.447 -	if (dev->page == NULL)
  71.448 -		return -1;
  71.449 -
  71.450 -	return 0;
  71.451 -}
  71.452 -
  71.453 -static void xenfb_unbind(struct xenfb_device *dev)
  71.454 -{
  71.455 -	if (dev->page) {
  71.456 -		munmap(dev->page, XC_PAGE_SIZE);
  71.457 -		dev->page = NULL;
  71.458 -	}
  71.459 -        if (dev->port >= 0) {
  71.460 -		xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
  71.461 -		dev->port = -1;
  71.462 -	}
  71.463 -}
  71.464 -
  71.465 -static int xenfb_wait_for_frontend_connected(struct xenfb_device *dev)
  71.466 -{
  71.467 -	switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
  71.468 -				     1 << XenbusStateConnected)) {
  71.469 -	case XenbusStateConnected:
  71.470 -		break;
  71.471 -	default:
  71.472 -		return -1;
  71.473 -	}
  71.474 -
  71.475 -	return 0;
  71.476 -}
  71.477 -
  71.478 -static void xenfb_dev_fatal(struct xenfb_device *dev, int err,
  71.479 -			    const char *fmt, ...)
  71.480 -{
  71.481 -	struct xs_handle *xsh = dev->xenfb->xsh;
  71.482 -	va_list ap;
  71.483 -	char errdir[80];
  71.484 -	char buf[1024];
  71.485 -	int n;
  71.486 -
  71.487 -	fprintf(stderr, "%s ", dev->nodename); /* somewhat crude */
  71.488 -	va_start(ap, fmt);
  71.489 -	vfprintf(stderr, fmt, ap);
  71.490 -	va_end(ap);
  71.491 -	if (err)
  71.492 -		fprintf(stderr, " (%s)", strerror(err));
  71.493 -	putc('\n', stderr);
  71.494 -
  71.495 -	if (!xenfb_path_in_dom(xsh, errdir, sizeof(errdir), 0,
  71.496 -			       "error/%s", dev->nodename))
  71.497 -		goto out;	/* FIXME complain */
  71.498 -
  71.499 -	va_start(ap, fmt);
  71.500 -	n = snprintf(buf, sizeof(buf), "%d ", err);
  71.501 -	snprintf(buf + n, sizeof(buf) - n, fmt, ap);
  71.502 -	va_end(ap);
  71.503 -
  71.504 -	if (xenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0)
  71.505 -		goto out;	/* FIXME complain */
  71.506 -
  71.507 - out:
  71.508 -	xenfb_switch_state(dev, XenbusStateClosing);
  71.509 -}
  71.510 -
  71.511 -int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
  71.512 -{
  71.513 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.514 -	struct xs_handle *xsh = xenfb->xsh;
  71.515 -	int val, serrno;
  71.516 -	struct xenfb_page *fb_page;
  71.517 -
  71.518 -	xenfb_detach_dom(xenfb);
  71.519 -
  71.520 -	xenfb_device_set_domain(&xenfb->fb, domid);
  71.521 -	xenfb_device_set_domain(&xenfb->kbd, domid);
  71.522 -
  71.523 -	if (xenfb_wait_for_backend_creation(&xenfb->fb) < 0)
  71.524 -		goto error;
  71.525 -	if (xenfb_wait_for_backend_creation(&xenfb->kbd) < 0)
  71.526 -		goto error;
  71.527 -
  71.528 -	if (xenfb_xs_printf(xsh, xenfb->kbd.nodename, "feature-abs-pointer", "1"))
  71.529 -		goto error;
  71.530 -	if (xenfb_switch_state(&xenfb->fb, XenbusStateInitWait))
  71.531 -		goto error;
  71.532 -	if (xenfb_switch_state(&xenfb->kbd, XenbusStateInitWait))
  71.533 -		goto error;
  71.534 -
  71.535 -	if (xenfb_hotplug(&xenfb->fb) < 0)
  71.536 -		goto error;
  71.537 -	if (xenfb_hotplug(&xenfb->kbd) < 0)
  71.538 -		goto error;
  71.539 -
  71.540 -	if (!xs_watch(xsh, xenfb->fb.otherend, ""))
  71.541 -		goto error;
  71.542 -	if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
  71.543 -		goto error;
  71.544 -
  71.545 -	if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0)
  71.546 -		goto error;
  71.547 -	if (xenfb_wait_for_frontend_initialised(&xenfb->kbd) < 0)
  71.548 -		goto error;
  71.549 -
  71.550 -	if (xenfb_bind(&xenfb->fb) < 0)
  71.551 -		goto error;
  71.552 -	if (xenfb_bind(&xenfb->kbd) < 0)
  71.553 -		goto error;
  71.554 -
  71.555 -	if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "feature-update",
  71.556 -			    "%d", &val) < 0)
  71.557 -		val = 0;
  71.558 -	if (!val) {
  71.559 -		errno = ENOTSUP;
  71.560 -		goto error;
  71.561 -	}
  71.562 -	if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "protocol", "%63s",
  71.563 -			    xenfb->protocol) < 0)
  71.564 -		xenfb->protocol[0] = '\0';
  71.565 -	xenfb_xs_printf(xsh, xenfb->fb.nodename, "request-update", "1");
  71.566 -
  71.567 -	/* TODO check for permitted ranges */
  71.568 -	fb_page = xenfb->fb.page;
  71.569 -	xenfb->pub.depth = fb_page->depth;
  71.570 -	xenfb->pub.width = fb_page->width;
  71.571 -	xenfb->pub.height = fb_page->height;
  71.572 -	/* TODO check for consistency with the above */
  71.573 -	xenfb->fb_len = fb_page->mem_length;
  71.574 -	xenfb->pub.row_stride = fb_page->line_length;
  71.575 -
  71.576 -	if (xenfb_map_fb(xenfb, domid) < 0)
  71.577 -		goto error;
  71.578 -
  71.579 -	if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))
  71.580 -		goto error;
  71.581 -	if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))
  71.582 -		goto error;
  71.583 -
  71.584 -	if (xenfb_wait_for_frontend_connected(&xenfb->kbd) < 0)
  71.585 -		goto error;
  71.586 -	if (xenfb_xs_scanf1(xsh, xenfb->kbd.otherend, "request-abs-pointer",
  71.587 -			    "%d", &val) < 0)
  71.588 -		val = 0;
  71.589 -	xenfb->pub.abs_pointer_wanted = val;
  71.590 -
  71.591 -	return 0;
  71.592 -
  71.593 - error:
  71.594 -	serrno = errno;
  71.595 -	xenfb_detach_dom(xenfb);
  71.596 -	xenfb_dev_fatal(&xenfb->fb, serrno, "on fire");
  71.597 -	xenfb_dev_fatal(&xenfb->kbd, serrno, "on fire");
  71.598 -        errno = serrno;
  71.599 -        return -1;
  71.600 -}
  71.601 -
  71.602 -static void xenfb_detach_dom(struct xenfb_private *xenfb)
  71.603 -{
  71.604 -	xenfb_unbind(&xenfb->fb);
  71.605 -	xenfb_unbind(&xenfb->kbd);
  71.606 -	if (xenfb->pub.pixels) {
  71.607 -		munmap(xenfb->pub.pixels, xenfb->fb_len);
  71.608 -		xenfb->pub.pixels = NULL;
  71.609 -	}
  71.610 -}
  71.611 -
  71.612 -static void xenfb_on_fb_event(struct xenfb_private *xenfb)
  71.613 -{
  71.614 -	uint32_t prod, cons;
  71.615 -	struct xenfb_page *page = xenfb->fb.page;
  71.616 -
  71.617 -	prod = page->out_prod;
  71.618 -	if (prod == page->out_cons)
  71.619 -		return;
  71.620 -	rmb();			/* ensure we see ring contents up to prod */
  71.621 -	for (cons = page->out_cons; cons != prod; cons++) {
  71.622 -		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
  71.623 -
  71.624 -		switch (event->type) {
  71.625 -		case XENFB_TYPE_UPDATE:
  71.626 -                    if (xenfb->pub.update)
  71.627 -			xenfb->pub.update(&xenfb->pub,
  71.628 -					  event->update.x, event->update.y,
  71.629 -					  event->update.width, event->update.height);
  71.630 -                    break;
  71.631 -		}
  71.632 -	}
  71.633 -	mb();			/* ensure we're done with ring contents */
  71.634 -	page->out_cons = cons;
  71.635 -	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
  71.636 -}
  71.637 -
  71.638 -static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
  71.639 -{
  71.640 -	struct xenkbd_page *page = xenfb->kbd.page;
  71.641 -
  71.642 -	/* We don't understand any keyboard events, so just ignore them. */
  71.643 -	if (page->out_prod == page->out_cons)
  71.644 -		return;
  71.645 -	page->out_cons = page->out_prod;
  71.646 -	xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
  71.647 -}
  71.648 -
  71.649 -static int xenfb_on_state_change(struct xenfb_device *dev)
  71.650 -{
  71.651 -	enum xenbus_state state;
  71.652 -
  71.653 -	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
  71.654 -
  71.655 -	switch (state) {
  71.656 -	case XenbusStateUnknown:
  71.657 -		/* There was an error reading the frontend state.  The
  71.658 -		   domain has probably gone away; in any case, there's
  71.659 -		   not much point in us continuing. */
  71.660 -		return -1;
  71.661 -	case XenbusStateInitialising:
  71.662 -	case XenbusStateInitWait:
  71.663 -	case XenbusStateInitialised:
  71.664 -	case XenbusStateConnected:
  71.665 -		break;
  71.666 -	case XenbusStateClosing:
  71.667 -		xenfb_unbind(dev);
  71.668 -		xenfb_switch_state(dev, state);
  71.669 -		break;
  71.670 -	case XenbusStateClosed:
  71.671 -		xenfb_switch_state(dev, state);
  71.672 -	}
  71.673 -	return 0;
  71.674 -}
  71.675 -
  71.676 -/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
  71.677 -int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
  71.678 -{
  71.679 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.680 -	evtchn_port_t port;
  71.681 -	unsigned dummy;
  71.682 -	char **vec;
  71.683 -	int r;
  71.684 -
  71.685 -	if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
  71.686 -		port = xc_evtchn_pending(xenfb->evt_xch);
  71.687 -		if (port == -1)
  71.688 -			return -1;
  71.689 -
  71.690 -		if (port == xenfb->fb.port)
  71.691 -			xenfb_on_fb_event(xenfb);
  71.692 -		else if (port == xenfb->kbd.port)
  71.693 -			xenfb_on_kbd_event(xenfb);
  71.694 -
  71.695 -		if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
  71.696 -			return -1;
  71.697 -	}
  71.698 -
  71.699 -	if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
  71.700 -		vec = xs_read_watch(xenfb->xsh, &dummy);
  71.701 -		free(vec);
  71.702 -		r = xenfb_on_state_change(&xenfb->fb);
  71.703 -		if (r == 0)
  71.704 -			r = xenfb_on_state_change(&xenfb->kbd);
  71.705 -		if (r == -1)
  71.706 -			return -2;
  71.707 -	}
  71.708 -
  71.709 -	return 0;
  71.710 -}
  71.711 -
  71.712 -int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds)
  71.713 -{
  71.714 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.715 -	int fd1 = xc_evtchn_fd(xenfb->evt_xch);
  71.716 -	int fd2 = xs_fileno(xenfb->xsh);
  71.717 -
  71.718 -	FD_SET(fd1, readfds);
  71.719 -	FD_SET(fd2, readfds);
  71.720 -	return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
  71.721 -}
  71.722 -
  71.723 -static int xenfb_kbd_event(struct xenfb_private *xenfb,
  71.724 -			   union xenkbd_in_event *event)
  71.725 -{
  71.726 -	uint32_t prod;
  71.727 -	struct xenkbd_page *page = xenfb->kbd.page;
  71.728 -
  71.729 -	if (xenfb->kbd.state != XenbusStateConnected)
  71.730 -		return 0;
  71.731 -
  71.732 -	prod = page->in_prod;
  71.733 -	if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
  71.734 -		errno = EAGAIN;
  71.735 -		return -1;
  71.736 -	}
  71.737 -
  71.738 -	mb();			/* ensure ring space available */
  71.739 -	XENKBD_IN_RING_REF(page, prod) = *event;
  71.740 -	wmb();			/* ensure ring contents visible */
  71.741 -	page->in_prod = prod + 1;
  71.742 -	return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
  71.743 -}
  71.744 -
  71.745 -int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
  71.746 -{
  71.747 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.748 -	union xenkbd_in_event event;
  71.749 -
  71.750 -	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
  71.751 -	event.type = XENKBD_TYPE_KEY;
  71.752 -	event.key.pressed = down ? 1 : 0;
  71.753 -	event.key.keycode = keycode;
  71.754 -
  71.755 -	return xenfb_kbd_event(xenfb, &event);
  71.756 -}
  71.757 -
  71.758 -int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
  71.759 -{
  71.760 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.761 -	union xenkbd_in_event event;
  71.762 -
  71.763 -	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
  71.764 -	event.type = XENKBD_TYPE_MOTION;
  71.765 -	event.motion.rel_x = rel_x;
  71.766 -	event.motion.rel_y = rel_y;
  71.767 -
  71.768 -	return xenfb_kbd_event(xenfb, &event);
  71.769 -}
  71.770 -
  71.771 -int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
  71.772 -{
  71.773 -	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
  71.774 -	union xenkbd_in_event event;
  71.775 -
  71.776 -	memset(&event, 0, XENKBD_IN_EVENT_SIZE);
  71.777 -	event.type = XENKBD_TYPE_POS;
  71.778 -	event.pos.abs_x = abs_x;
  71.779 -	event.pos.abs_y = abs_y;
  71.780 -
  71.781 -	return xenfb_kbd_event(xenfb, &event);
  71.782 -}
    72.1 --- a/tools/xenfb/xenfb.h	Tue Oct 30 11:33:55 2007 -0600
    72.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.3 @@ -1,35 +0,0 @@
    72.4 -#ifndef _XENFB_H_
    72.5 -#define _XENFB_H_
    72.6 -
    72.7 -#include <stdbool.h>
    72.8 -#include <sys/types.h>
    72.9 -
   72.10 -struct xenfb
   72.11 -{
   72.12 -	void *pixels;
   72.13 -
   72.14 -	int row_stride;
   72.15 -	int depth;
   72.16 -	int width;
   72.17 -	int height;
   72.18 -	int abs_pointer_wanted;
   72.19 -
   72.20 -	void *user_data;
   72.21 -
   72.22 -	void (*update)(struct xenfb *xenfb, int x, int y, int width, int height);
   72.23 -};
   72.24 -
   72.25 -struct xenfb *xenfb_new(void);
   72.26 -void xenfb_delete(struct xenfb *xenfb);
   72.27 -void xenfb_teardown(struct xenfb *xenfb);
   72.28 -
   72.29 -int xenfb_attach_dom(struct xenfb *xenfb, int domid);
   72.30 -
   72.31 -int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds);
   72.32 -int xenfb_poll(struct xenfb *xenfb, fd_set *readfds);
   72.33 -
   72.34 -int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
   72.35 -int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
   72.36 -int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
   72.37 -
   72.38 -#endif
    73.1 --- a/tools/xenstore/xenstored_watch.c	Tue Oct 30 11:33:55 2007 -0600
    73.2 +++ b/tools/xenstore/xenstored_watch.c	Tue Oct 30 15:34:44 2007 -0600
    73.3 @@ -59,7 +59,16 @@ static void add_event(struct connection 
    73.4  	if (!check_event_node(name)) {
    73.5  		/* Can this conn load node, or see that it doesn't exist? */
    73.6  		struct node *node = get_node(conn, name, XS_PERM_READ);
    73.7 -		if (!node && errno != ENOENT)
    73.8 +		/*
    73.9 +		 * XXX We allow EACCES here because otherwise a non-dom0
   73.10 +		 * backend driver cannot watch for disappearance of a frontend
   73.11 +		 * xenstore directory. When the directory disappears, we
   73.12 +		 * revert to permissions of the parent directory for that path,
   73.13 +		 * which will typically disallow access for the backend.
   73.14 +		 * But this breaks device-channel teardown!
   73.15 +		 * Really we should fix this better...
   73.16 +		 */
   73.17 +		if (!node && errno != ENOENT && errno != EACCES)
   73.18  			return;
   73.19  	}
   73.20  
    74.1 --- a/tools/xentrace/xentrace.c	Tue Oct 30 11:33:55 2007 -0600
    74.2 +++ b/tools/xentrace/xentrace.c	Tue Oct 30 15:34:44 2007 -0600
    74.3 @@ -394,7 +394,7 @@ int monitor_tbufs(int outfd)
    74.4              }
    74.5  
    74.6              mb(); /* read buffer, then update cons. */
    74.7 -            meta[i]->cons = meta[i]->prod;
    74.8 +            meta[i]->cons = prod;
    74.9          }
   74.10  
   74.11          nanosleep(&opts.poll_sleep, NULL);
    75.1 --- a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py	Tue Oct 30 11:33:55 2007 -0600
    75.2 +++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py	Tue Oct 30 15:34:44 2007 -0600
    75.3 @@ -38,7 +38,8 @@ class XenAPIConfig:
    75.4                                          'memory_dynamic_max' ],
    75.5                             'kernel' : 'PV_kernel',
    75.6                             'ramdisk': 'PV_ramdisk',
    75.7 -                           'root'   : 'PV_args'}
    75.8 +                           'root'   : 'PV_args',
    75.9 +                           'extra'  : 'PV_args' }
   75.10          if isACMEnabled():
   75.11              #A default so every VM can start with ACM enabled
   75.12              self.opts["security_label"] = "ACM:xm-test:red"
   75.13 @@ -47,6 +48,8 @@ class XenAPIConfig:
   75.14          """Set an option in the config"""
   75.15          if name == "memory":
   75.16              value <<= 20
   75.17 +        if name == "root":
   75.18 +            value = "root=" + value
   75.19          if name in self.opttrlate.keys():
   75.20              _name = self.opttrlate[name]
   75.21          else:
   75.22 @@ -56,7 +59,11 @@ class XenAPIConfig:
   75.23              for _n in _name:
   75.24                  self.opts[_n] = value
   75.25          else:
   75.26 -            self.opts[_name] = value
   75.27 +            if not self.opts.get(_name) or \
   75.28 +               not _name in [ "PV_args" ]:
   75.29 +                self.opts[_name] = value
   75.30 +            else:
   75.31 +                self.opts[_name] += " " + value
   75.32  
   75.33      def getOpt(self, name):
   75.34          """Return the value of a config option"""
    76.1 --- a/tools/xm-test/tests/security-acm/08_security-acm_xapi.py	Tue Oct 30 11:33:55 2007 -0600
    76.2 +++ b/tools/xm-test/tests/security-acm/08_security-acm_xapi.py	Tue Oct 30 15:34:44 2007 -0600
    76.3 @@ -19,6 +19,9 @@ vm_label_green  = xsconstants.ACM_POLICY
    76.4  vdi_label_red   = xsconstants.ACM_POLICY_ID + ":xm-test:red"
    76.5  vdi_label_green = xsconstants.ACM_POLICY_ID + ":xm-test:green"
    76.6  
    76.7 +vm_label_unlabeled = xsconstants.ACM_POLICY_ID + ":xm-test:" + \
    76.8 +                     acmpolicy.ACM_LABEL_UNLABELED
    76.9 +
   76.10  vdi_file = "/dev/ram0"
   76.11  vdi_path = "phy:" + vdi_file
   76.12  
   76.13 @@ -105,7 +108,7 @@ if int(res) != 0:
   76.14      FAIL("Should be able to unlabel the domain while it's halted.")
   76.15  
   76.16  res = session.xenapi.VM.get_security_label(vm_uuid)
   76.17 -if res != "":
   76.18 +if res != vm_label_unlabeled:
   76.19      FAIL("Unexpected VM security label after removal: %s" % res)
   76.20  
   76.21  res = session.xenapi.VM.set_security_label(vm_uuid, vm_label_red, res)
    77.1 --- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py	Tue Oct 30 11:33:55 2007 -0600
    77.2 +++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py	Tue Oct 30 15:34:44 2007 -0600
    77.3 @@ -17,7 +17,7 @@ from vtpm_utils import *
    77.4  import commands
    77.5  import os
    77.6  
    77.7 -VTPM_RECORD_KEYS = [ 'backend', 'VM', 'uuid' ]
    77.8 +VTPM_RECORD_KEYS = [ 'backend', 'VM', 'uuid', 'other_config' ]
    77.9  
   77.10  try:
   77.11      # XmTestAPIDomain tries to establish a connection to XenD
    78.1 --- a/unmodified_drivers/linux-2.6/README	Tue Oct 30 11:33:55 2007 -0600
    78.2 +++ b/unmodified_drivers/linux-2.6/README	Tue Oct 30 15:34:44 2007 -0600
    78.3 @@ -1,12 +1,12 @@
    78.4  To build:
    78.5  
    78.6  1. ./mkbuildtree
    78.7 -   NB. You can override paths to Xen sources and XenLinux sources via
    78.8 -       the XEN and XL environment variable.
    78.9 +   NB. You can override paths to Xen sources and a (stub) XenLinux
   78.10 +       build tree via the XEN and XL environment variable.
   78.11  
   78.12 -2. make -C /path/to/kernel/source M=$PWD modules
   78.13 -   NB. The kernel sources here are your native kernel build tree, not
   78.14 -       the XenLinux sources referred to in step 1.
   78.15 +2. make -C /path/to/kernel/build M=$PWD modules
   78.16 +   NB. This is your native kernel build tree (or a distro provided
   78.17 +       stub), not the XenLinux sources referred to in step 1.
   78.18  
   78.19  You get four modules, xen-platform-pci.ko, xenbus.ko, xen-vbd.ko, and
   78.20  xen-vnif.ko.  Load xen-platform-pci first, then xenbus, and then
    79.1 --- a/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h	Tue Oct 30 11:33:55 2007 -0600
    79.2 +++ b/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h	Tue Oct 30 15:34:44 2007 -0600
    79.3 @@ -125,4 +125,12 @@ extern char *kasprintf(gfp_t gfp, const 
    79.4  #define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
    79.5  #endif
    79.6  
    79.7 +#if defined(_LINUX_INTERRUPT_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
    79.8 +typedef irqreturn_t (*irq_handler_t)(int, void *, struct pt_regs *);
    79.9  #endif
   79.10 +
   79.11 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
   79.12 +#define setup_xen_features xen_setup_features
   79.13 +#endif
   79.14 +
   79.15 +#endif
    80.1 --- a/unmodified_drivers/linux-2.6/overrides.mk	Tue Oct 30 11:33:55 2007 -0600
    80.2 +++ b/unmodified_drivers/linux-2.6/overrides.mk	Tue Oct 30 15:34:44 2007 -0600
    80.3 @@ -11,4 +11,4 @@ ifeq ($(ARCH),ia64)
    80.4    EXTRA_CFLAGS += -DCONFIG_VMX_GUEST
    80.5  endif
    80.6  
    80.7 -EXTRA_CFLAGS += -include $(srctree)/include/linux/autoconf.h
    80.8 +EXTRA_CFLAGS += -include $(objtree)/include/linux/autoconf.h
    81.1 --- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c	Tue Oct 30 11:33:55 2007 -0600
    81.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c	Tue Oct 30 15:34:44 2007 -0600
    81.3 @@ -28,7 +28,6 @@
    81.4   * IN THE SOFTWARE.
    81.5   */
    81.6  
    81.7 -#include <linux/config.h>
    81.8  #include <linux/module.h>
    81.9  #include <linux/kernel.h>
   81.10  #include <linux/spinlock.h>
   81.11 @@ -48,7 +47,7 @@ void *shared_info_area;
   81.12  
   81.13  static struct {
   81.14  	spinlock_t lock;
   81.15 -	irqreturn_t(*handler) (int, void *, struct pt_regs *);
   81.16 +	irq_handler_t handler;
   81.17  	void *dev_id;
   81.18  	int evtchn;
   81.19  	int close:1; /* close on unbind_from_irqhandler()? */
   81.20 @@ -146,7 +145,7 @@ EXPORT_SYMBOL(unmask_evtchn);
   81.21  
   81.22  int bind_listening_port_to_irqhandler(
   81.23  	unsigned int remote_domain,
   81.24 -	irqreturn_t (*handler)(int, void *, struct pt_regs *),
   81.25 +	irq_handler_t handler,
   81.26  	unsigned long irqflags,
   81.27  	const char *devname,
   81.28  	void *dev_id)
   81.29 @@ -187,7 +186,7 @@ EXPORT_SYMBOL(bind_listening_port_to_irq
   81.30  
   81.31  int bind_caller_port_to_irqhandler(
   81.32  	unsigned int caller_port,
   81.33 -	irqreturn_t (*handler)(int, void *, struct pt_regs *),
   81.34 +	irq_handler_t handler,
   81.35  	unsigned long irqflags,
   81.36  	const char *devname,
   81.37  	void *dev_id)
   81.38 @@ -254,13 +253,18 @@ void notify_remote_via_irq(int irq)
   81.39  }
   81.40  EXPORT_SYMBOL(notify_remote_via_irq);
   81.41  
   81.42 -static irqreturn_t evtchn_interrupt(int irq, void *dev_id,
   81.43 -				    struct pt_regs *regs)
   81.44 +static irqreturn_t evtchn_interrupt(int irq, void *dev_id
   81.45 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
   81.46 +				    , struct pt_regs *regs
   81.47 +#else
   81.48 +# define handler(irq, dev_id, regs) handler(irq, dev_id)
   81.49 +#endif
   81.50 +				    )
   81.51  {
   81.52  	unsigned int l1i, port;
   81.53  	/* XXX: All events are bound to vcpu0 but irq may be redirected. */
   81.54  	int cpu = 0; /*smp_processor_id();*/
   81.55 -	irqreturn_t(*handler) (int, void *, struct pt_regs *);
   81.56 +	irq_handler_t handler;
   81.57  	shared_info_t *s = shared_info_area;
   81.58  	vcpu_info_t *v = &s->vcpu_info[cpu];
   81.59  	unsigned long l1, l2;
   81.60 @@ -331,6 +335,10 @@ int xen_irq_init(struct pci_dev *pdev)
   81.61  		spin_lock_init(&irq_evtchn[irq].lock);
   81.62  
   81.63  	return request_irq(pdev->irq, evtchn_interrupt,
   81.64 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
   81.65  			   SA_SHIRQ | SA_SAMPLE_RANDOM | SA_INTERRUPT,
   81.66 +#else
   81.67 +			   IRQF_SHARED | IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
   81.68 +#endif
   81.69  			   "xen-platform-pci", pdev);
   81.70  }
    82.1 --- a/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c	Tue Oct 30 11:33:55 2007 -0600
    82.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c	Tue Oct 30 15:34:44 2007 -0600
    82.3 @@ -1,4 +1,3 @@
    82.4 -#include <linux/config.h>
    82.5  #include <linux/cpumask.h>
    82.6  #include <linux/preempt.h>
    82.7  #include <xen/evtchn.h>
    83.1 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Tue Oct 30 11:33:55 2007 -0600
    83.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Tue Oct 30 15:34:44 2007 -0600
    83.3 @@ -367,7 +367,11 @@ static int __init platform_pci_module_in
    83.4  {
    83.5  	int rc;
    83.6  
    83.7 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
    83.8  	rc = pci_module_init(&platform_driver);
    83.9 +#else
   83.10 +	rc = pci_register_driver(&platform_driver);
   83.11 +#endif
   83.12  	if (rc) {
   83.13  		printk(KERN_INFO DRV_NAME
   83.14  		       ": No platform pci device model found\n");
    84.1 --- a/xen/arch/ia64/vmx/mmio.c	Tue Oct 30 11:33:55 2007 -0600
    84.2 +++ b/xen/arch/ia64/vmx/mmio.c	Tue Oct 30 15:34:44 2007 -0600
    84.3 @@ -55,54 +55,69 @@ static struct hvm_buffered_io_range
    84.4  static int hvm_buffered_io_intercept(ioreq_t *p)
    84.5  {
    84.6      struct vcpu *v = current;
    84.7 -    spinlock_t  *buffered_io_lock;
    84.8 -    buffered_iopage_t *buffered_iopage =
    84.9 +    buffered_iopage_t *pg =
   84.10          (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
   84.11 -    unsigned long tmp_write_pointer = 0;
   84.12 +    buf_ioreq_t bp;
   84.13      int i;
   84.14  
   84.15 +    /* Ensure buffered_iopage fits in a page */
   84.16 +    BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
   84.17 +
   84.18      /* ignore READ ioreq_t! */
   84.19 -    if ( p->dir == IOREQ_READ )
   84.20 +    if (p->dir == IOREQ_READ)
   84.21          return 0;
   84.22  
   84.23 -    for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
   84.24 -        if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
   84.25 -             p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
   84.26 -                                     hvm_buffered_io_ranges[i]->length )
   84.27 +    for (i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++) {
   84.28 +        if (p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
   84.29 +            p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
   84.30 +                                    hvm_buffered_io_ranges[i]->length)
   84.31              break;
   84.32      }
   84.33  
   84.34 -    if ( i == HVM_BUFFERED_IO_RANGE_NR )
   84.35 +    if (i == HVM_BUFFERED_IO_RANGE_NR)
   84.36          return 0;
   84.37  
   84.38 -    buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
   84.39 -    spin_lock(buffered_io_lock);
   84.40 +    bp.type = p->type;
   84.41 +    bp.dir = p->dir;
   84.42 +    switch (p->size) {
   84.43 +    case 1:
   84.44 +        bp.size = 0;
   84.45 +        break;
   84.46 +    case 2:
   84.47 +        bp.size = 1;
   84.48 +        break;
   84.49 +    default:
   84.50 +	/* Could use quad word semantics, but it only appears
   84.51 +	 * to be useful for timeoffset data. */
   84.52 +        return 0;
   84.53 +    }
   84.54 +    bp.data = (uint16_t)p->data;
   84.55 +    bp.addr = (uint32_t)p->addr;
   84.56  
   84.57 -    if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer ==
   84.58 -         (unsigned long)IOREQ_BUFFER_SLOT_NUM ) {
   84.59 +    spin_lock(&v->domain->arch.hvm_domain.buffered_io_lock);
   84.60 +
   84.61 +    if (pg->write_pointer - pg->read_pointer == IOREQ_BUFFER_SLOT_NUM) {
   84.62          /* the queue is full.
   84.63           * send the iopacket through the normal path.
   84.64           * NOTE: The arithimetic operation could handle the situation for
   84.65           * write_pointer overflow.
   84.66           */
   84.67 -        spin_unlock(buffered_io_lock);
   84.68 +        spin_unlock(&v->domain->arch.hvm_domain.buffered_io_lock);
   84.69          return 0;
   84.70      }
   84.71  
   84.72 -    tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM;
   84.73 -
   84.74 -    memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t));
   84.75 +    memcpy(&pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
   84.76 +           &bp, sizeof(bp));
   84.77  
   84.78 -    /*make the ioreq_t visible before write_pointer*/
   84.79 +    /* Make the ioreq_t visible before write_pointer */
   84.80      wmb();
   84.81 -    buffered_iopage->write_pointer++;
   84.82 +    pg->write_pointer++;
   84.83  
   84.84 -    spin_unlock(buffered_io_lock);
   84.85 +    spin_unlock(&v->domain->arch.hvm_domain.buffered_io_lock);
   84.86  
   84.87      return 1;
   84.88  }
   84.89  
   84.90 -
   84.91  static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
   84.92  {
   84.93      struct vcpu *v = current;
   84.94 @@ -110,32 +125,36 @@ static void low_mmio_access(VCPU *vcpu, 
   84.95      ioreq_t *p;
   84.96  
   84.97      vio = get_vio(v->domain, v->vcpu_id);
   84.98 -    if (vio == 0) {
   84.99 -        panic_domain(NULL,"bad shared page: %lx", (unsigned long)vio);
  84.100 -    }
  84.101 +    if (!vio)
  84.102 +        panic_domain(NULL, "bad shared page");
  84.103 +
  84.104      p = &vio->vp_ioreq;
  84.105 +
  84.106      p->addr = pa;
  84.107      p->size = s;
  84.108      p->count = 1;
  84.109 -    p->dir = dir;
  84.110 -    if (dir==IOREQ_WRITE)     // write;
  84.111 +    if (dir == IOREQ_WRITE)
  84.112          p->data = *val;
  84.113 -    else if (dir == IOREQ_READ)
  84.114 -        p->data = 0;          // clear all bits
  84.115 +    else
  84.116 +        p->data = 0;
  84.117      p->data_is_ptr = 0;
  84.118 +    p->dir = dir;
  84.119 +    p->df = 0;
  84.120      p->type = 1;
  84.121 -    p->df = 0;
  84.122  
  84.123      p->io_count++;
  84.124 +
  84.125      if (hvm_buffered_io_intercept(p)) {
  84.126          p->state = STATE_IORESP_READY;
  84.127          vmx_io_assist(v);
  84.128 -        return;
  84.129 -    } else 
  84.130 -        vmx_send_assist_req(v);
  84.131 -    if (dir == IOREQ_READ) { // read
  84.132 +        if (dir != IOREQ_READ)
  84.133 +            return;
  84.134 +    }
  84.135 +
  84.136 +    vmx_send_assist_req(v);
  84.137 +    if (dir == IOREQ_READ)
  84.138          *val = p->data;
  84.139 -    }
  84.140 +
  84.141      return;
  84.142  }
  84.143  
  84.144 @@ -227,16 +246,18 @@ static void legacy_io_access(VCPU *vcpu,
  84.145      ioreq_t *p;
  84.146  
  84.147      vio = get_vio(v->domain, v->vcpu_id);
  84.148 -    if (vio == 0) {
  84.149 -        panic_domain(NULL,"bad shared page\n");
  84.150 -    }
  84.151 +    if (!vio)
  84.152 +        panic_domain(NULL, "bad shared page\n");
  84.153 +
  84.154      p = &vio->vp_ioreq;
  84.155 -    p->addr = TO_LEGACY_IO(pa&0x3ffffffUL);
  84.156 +    p->addr = TO_LEGACY_IO(pa & 0x3ffffffUL);
  84.157      p->size = s;
  84.158      p->count = 1;
  84.159      p->dir = dir;
  84.160 -    if (dir == IOREQ_WRITE)     // write;
  84.161 +    if (dir == IOREQ_WRITE)
  84.162          p->data = *val;
  84.163 +    else
  84.164 +        p->data = 0;
  84.165      p->data_is_ptr = 0;
  84.166      p->type = 0;
  84.167      p->df = 0;
    85.1 --- a/xen/arch/x86/Makefile	Tue Oct 30 11:33:55 2007 -0600
    85.2 +++ b/xen/arch/x86/Makefile	Tue Oct 30 15:34:44 2007 -0600
    85.3 @@ -46,6 +46,7 @@ obj-y += usercopy.o
    85.4  obj-y += x86_emulate.o
    85.5  obj-y += machine_kexec.o
    85.6  obj-y += crash.o
    85.7 +obj-y += tboot.o
    85.8  
    85.9  obj-$(crash_debug) += gdbstub.o
   85.10  
    86.1 --- a/xen/arch/x86/acpi/boot.c	Tue Oct 30 11:33:55 2007 -0600
    86.2 +++ b/xen/arch/x86/acpi/boot.c	Tue Oct 30 15:34:44 2007 -0600
    86.3 @@ -36,6 +36,7 @@
    86.4  #include <asm/apic.h>
    86.5  #include <asm/io.h>
    86.6  #include <asm/mpspec.h>
    86.7 +#include <asm/processor.h>
    86.8  #include <mach_apic.h>
    86.9  #include <mach_mpparse.h>
   86.10  
    87.1 --- a/xen/arch/x86/acpi/power.c	Tue Oct 30 11:33:55 2007 -0600
    87.2 +++ b/xen/arch/x86/acpi/power.c	Tue Oct 30 15:34:44 2007 -0600
    87.3 @@ -25,6 +25,7 @@
    87.4  #include <xen/domain.h>
    87.5  #include <xen/console.h>
    87.6  #include <public/platform.h>
    87.7 +#include <asm/tboot.h>
    87.8  
    87.9  #define pmprintk(_l, _f, _a...) printk(_l "<PM> " _f "\n", ## _a )
   87.10  
   87.11 @@ -94,11 +95,19 @@ static void acpi_sleep_prepare(u32 state
   87.12      wakeup_vector_va = __acpi_map_table(
   87.13          acpi_sinfo.wakeup_vector, sizeof(uint64_t));
   87.14      if ( acpi_sinfo.vector_width == 32 )
   87.15 -        *(uint32_t *)wakeup_vector_va =
   87.16 -            (uint32_t)bootsym_phys(wakeup_start);
   87.17 +    {
   87.18 +            *(uint32_t *)wakeup_vector_va =
   87.19 +                tboot_in_measured_env() ?
   87.20 +                (uint32_t)g_tboot_shared->s3_tb_wakeup_entry :
   87.21 +                (uint32_t)bootsym_phys(wakeup_start);
   87.22 +    }
   87.23      else
   87.24 -        *(uint64_t *)wakeup_vector_va =
   87.25 -            (uint64_t)bootsym_phys(wakeup_start);
   87.26 +    {
   87.27 +            *(uint64_t *)wakeup_vector_va =
   87.28 +                tboot_in_measured_env() ?
   87.29 +                (uint64_t)g_tboot_shared->s3_tb_wakeup_entry :
   87.30 +	        (uint64_t)bootsym_phys(wakeup_start);
   87.31 +    }
   87.32  }
   87.33  
   87.34  static void acpi_sleep_post(u32 state) {}
   87.35 @@ -155,6 +164,10 @@ static int enter_state(u32 state)
   87.36  
   87.37      pmprintk(XENLOG_DEBUG, "Back to C.");
   87.38  
   87.39 +    /* Restore CR4 and EFER from cached values. */
   87.40 +    write_cr4(read_cr4());
   87.41 +    write_efer(read_efer());
   87.42 +
   87.43      device_power_up();
   87.44  
   87.45      pmprintk(XENLOG_INFO, "Finishing wakeup from ACPI S%d state.", state);
   87.46 @@ -217,9 +230,43 @@ static int acpi_get_wake_status(void)
   87.47      return val;
   87.48  }
   87.49  
   87.50 +static void tboot_sleep(u8 sleep_state)
   87.51 +{
   87.52 +   uint32_t shutdown_type;
   87.53 +   
   87.54 +   *((struct acpi_sleep_info *)(unsigned long)g_tboot_shared->acpi_sinfo) =
   87.55 +       acpi_sinfo;
   87.56 +
   87.57 +   switch ( sleep_state )
   87.58 +   {
   87.59 +       case ACPI_STATE_S3:
   87.60 +           shutdown_type = TB_SHUTDOWN_S3;
   87.61 +           g_tboot_shared->s3_k_wakeup_entry =
   87.62 +	       (uint32_t)bootsym_phys(wakeup_start);
   87.63 +           break;
   87.64 +       case ACPI_STATE_S4:
   87.65 +           shutdown_type = TB_SHUTDOWN_S4;
   87.66 +           break;
   87.67 +       case ACPI_STATE_S5:
   87.68 +           shutdown_type = TB_SHUTDOWN_S5;
   87.69 +           break;
   87.70 +       default:
   87.71 +           return;
   87.72 +   }
   87.73 +
   87.74 +   tboot_shutdown(shutdown_type);
   87.75 +}
   87.76 +         
   87.77  /* System is really put into sleep state by this stub */
   87.78  acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
   87.79  {
   87.80 +    if ( tboot_in_measured_env() )
   87.81 +    {
   87.82 +        tboot_sleep(sleep_state);
   87.83 +        pmprintk(XENLOG_ERR, "TBOOT failed entering s3 state\n");
   87.84 +        return_ACPI_STATUS(AE_ERROR);
   87.85 +    }
   87.86 +
   87.87      ACPI_FLUSH_CPU_CACHE();
   87.88  
   87.89      outw((u16)acpi_sinfo.pm1a_cnt_val, acpi_sinfo.pm1a_cnt);
    88.1 --- a/xen/arch/x86/boot/cmdline.S	Tue Oct 30 11:33:55 2007 -0600
    88.2 +++ b/xen/arch/x86/boot/cmdline.S	Tue Oct 30 15:34:44 2007 -0600
    88.3 @@ -170,6 +170,12 @@ cmdline_parse_early:
    88.4          test    %eax,%eax
    88.5          setnz   bootsym_phys(skip_realmode)
    88.6  
    88.7 +        /* Check for 'tboot=' command-line option. */
    88.8 +        movl    $sym_phys(.Ltboot_opt),4(%esp)
    88.9 +        call    .Lfind_option
   88.10 +        test    %eax,%eax
   88.11 +        setnz   bootsym_phys(skip_realmode) /* tboot= implies no-real-mode */
   88.12 +
   88.13  .Lparse_edd:
   88.14          /* Check for 'edd=' command-line option. */
   88.15          movl    $sym_phys(.Ledd_opt),4(%esp)
   88.16 @@ -346,6 +352,8 @@ 1:      lodsw
   88.17          .asciz  "current"
   88.18  .Lno_rm_opt:
   88.19          .asciz  "no-real-mode"
   88.20 +.Ltboot_opt:
   88.21 +        .asciz  "tboot"
   88.22  .Ledid_opt:
   88.23          .asciz  "edid"
   88.24  .Ledid_force:
    89.1 --- a/xen/arch/x86/boot/trampoline.S	Tue Oct 30 11:33:55 2007 -0600
    89.2 +++ b/xen/arch/x86/boot/trampoline.S	Tue Oct 30 15:34:44 2007 -0600
    89.3 @@ -168,6 +168,10 @@ 1:      mov     $(BOOT_TRAMPOLINE>>4),%a
    89.4          /* Disable irqs before returning to protected mode. */
    89.5          cli
    89.6  
    89.7 +        /* Reset GDT and IDT. Some BIOSes clobber GDTR. */
    89.8 +        lidt    bootsym(idt_48)
    89.9 +        lgdt    bootsym(gdt_48)
   89.10 +
   89.11          /* Enter protected mode, and flush insn queue. */
   89.12          xor     %ax,%ax
   89.13          inc     %ax
    90.1 --- a/xen/arch/x86/domain.c	Tue Oct 30 11:33:55 2007 -0600
    90.2 +++ b/xen/arch/x86/domain.c	Tue Oct 30 15:34:44 2007 -0600
    90.3 @@ -50,7 +50,8 @@
    90.4  #endif
    90.5  
    90.6  DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
    90.7 -DEFINE_PER_CPU(__u64, efer);
    90.8 +DEFINE_PER_CPU(u64, efer);
    90.9 +DEFINE_PER_CPU(unsigned long, cr4);
   90.10  
   90.11  static void unmap_vcpu_info(struct vcpu *v);
   90.12  
   90.13 @@ -413,6 +414,8 @@ int vcpu_initialise(struct vcpu *v)
   90.14              v->arch.schedule_tail = continue_idle_domain;
   90.15              v->arch.cr3           = __pa(idle_pg_table);
   90.16          }
   90.17 +
   90.18 +        v->arch.guest_context.ctrlreg[4] = mmu_cr4_features;
   90.19      }
   90.20  
   90.21      v->arch.perdomain_ptes =
   90.22 @@ -568,13 +571,28 @@ void arch_domain_destroy(struct domain *
   90.23      free_xenheap_page(d->shared_info);
   90.24  }
   90.25  
   90.26 +unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4)
   90.27 +{
   90.28 +    unsigned long hv_cr4 = read_cr4(), hv_cr4_mask = ~X86_CR4_TSD;
   90.29 +    if ( cpu_has_de )
   90.30 +        hv_cr4_mask &= ~X86_CR4_DE;
   90.31 +
   90.32 +    if ( (guest_cr4 & hv_cr4_mask) !=
   90.33 +         (hv_cr4 & hv_cr4_mask & ~(X86_CR4_PGE|X86_CR4_PSE)) )
   90.34 +        gdprintk(XENLOG_WARNING,
   90.35 +                 "Attempt to change CR4 flags %08lx -> %08lx\n",
   90.36 +                 hv_cr4 & ~(X86_CR4_PGE|X86_CR4_PSE), guest_cr4);
   90.37 +
   90.38 +    return  (hv_cr4 & hv_cr4_mask) | (guest_cr4 & ~hv_cr4_mask);
   90.39 +}
   90.40 +
   90.41  /* This is called by arch_final_setup_guest and do_boot_vcpu */
   90.42  int arch_set_info_guest(
   90.43      struct vcpu *v, vcpu_guest_context_u c)
   90.44  {
   90.45      struct domain *d = v->domain;
   90.46      unsigned long cr3_pfn = INVALID_MFN;
   90.47 -    unsigned long flags;
   90.48 +    unsigned long flags, cr4;
   90.49      int i, rc = 0, compat;
   90.50  
   90.51      /* The context is a compat-mode one if the target domain is compat-mode;
   90.52 @@ -665,6 +683,10 @@ int arch_set_info_guest(
   90.53      /* Ensure real hardware interrupts are enabled. */
   90.54      v->arch.guest_context.user_regs.eflags |= EF_IE;
   90.55  
   90.56 +    cr4 = v->arch.guest_context.ctrlreg[4];
   90.57 +    v->arch.guest_context.ctrlreg[4] =
   90.58 +        (cr4 == 0) ? mmu_cr4_features : pv_guest_cr4_fixup(cr4);
   90.59 +
   90.60      if ( v->is_initialised )
   90.61          goto out;
   90.62  
   90.63 @@ -1194,6 +1216,9 @@ static void paravirt_ctxt_switch_to(stru
   90.64  {
   90.65      set_int80_direct_trap(v);
   90.66      switch_kernel_stack(v);
   90.67 +
   90.68 +    if ( unlikely(read_cr4() != v->arch.guest_context.ctrlreg[4]) )
   90.69 +        write_cr4(v->arch.guest_context.ctrlreg[4]);
   90.70  }
   90.71  
   90.72  #define loaddebug(_v,_reg) \
   90.73 @@ -1279,7 +1304,7 @@ void context_switch(struct vcpu *prev, s
   90.74      local_irq_disable();
   90.75  
   90.76      if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) )
   90.77 -        pt_freeze_time(prev);
   90.78 +        pt_save_timer(prev);
   90.79  
   90.80      set_current(next);
   90.81  
    91.1 --- a/xen/arch/x86/domain_build.c	Tue Oct 30 11:33:55 2007 -0600
    91.2 +++ b/xen/arch/x86/domain_build.c	Tue Oct 30 15:34:44 2007 -0600
    91.3 @@ -990,14 +990,16 @@ int __init construct_dom0(
    91.4              rc |= iomem_deny_access(dom0, mfn, mfn);
    91.5      }
    91.6  
    91.7 -    /* Remove access to E820_UNUSABLE I/O regions. */
    91.8 +    /* Remove access to E820_UNUSABLE I/O regions above 1MB. */
    91.9      for ( i = 0; i < e820.nr_map; i++ )
   91.10      {
   91.11 -        if ( e820.map[i].type != E820_UNUSABLE)
   91.12 -            continue;
   91.13 -        mfn = paddr_to_pfn(e820.map[i].addr);
   91.14 -        nr_pages = (e820.map[i].size + PAGE_SIZE - 1) >> PAGE_SHIFT;
   91.15 -        rc |= iomem_deny_access(dom0, mfn, mfn + nr_pages - 1);
   91.16 +        unsigned long sfn, efn;
   91.17 +        sfn = max_t(unsigned long, paddr_to_pfn(e820.map[i].addr), 0x100ul);
   91.18 +        efn = paddr_to_pfn(e820.map[i].addr + e820.map[i].size - 1);
   91.19 +        if ( (e820.map[i].type == E820_UNUSABLE) &&
   91.20 +             (e820.map[i].size != 0) &&
   91.21 +             (sfn <= efn) )
   91.22 +            rc |= iomem_deny_access(dom0, sfn, efn);
   91.23      }
   91.24  
   91.25      BUG_ON(rc != 0);
    92.1 --- a/xen/arch/x86/domctl.c	Tue Oct 30 11:33:55 2007 -0600
    92.2 +++ b/xen/arch/x86/domctl.c	Tue Oct 30 15:34:44 2007 -0600
    92.3 @@ -26,7 +26,6 @@
    92.4  #include <asm/hvm/cacheattr.h>
    92.5  #include <asm/processor.h>
    92.6  #include <xsm/xsm.h>
    92.7 -#include <xen/list.h>
    92.8  #include <asm/iommu.h>
    92.9  
   92.10  long arch_do_domctl(
   92.11 @@ -697,6 +696,79 @@ long arch_do_domctl(
   92.12      }
   92.13      break;
   92.14  
   92.15 +    case XEN_DOMCTL_set_ext_vcpucontext:
   92.16 +    case XEN_DOMCTL_get_ext_vcpucontext:
   92.17 +    {
   92.18 +        struct xen_domctl_ext_vcpucontext *evc;
   92.19 +        struct domain *d;
   92.20 +        struct vcpu *v;
   92.21 +
   92.22 +        evc = &domctl->u.ext_vcpucontext;
   92.23 +
   92.24 +        ret = (evc->size < sizeof(*evc)) ? -EINVAL : 0;
   92.25 +        evc->size = sizeof(*evc);
   92.26 +        if ( ret != 0 )
   92.27 +            break;
   92.28 +
   92.29 +        ret = -ESRCH;
   92.30 +        d = rcu_lock_domain_by_id(domctl->domain);
   92.31 +        if ( d == NULL )
   92.32 +            break;
   92.33 +
   92.34 +        ret = -ESRCH;
   92.35 +        if ( (evc->vcpu >= MAX_VIRT_CPUS) ||
   92.36 +             ((v = d->vcpu[evc->vcpu]) == NULL) )
   92.37 +            goto ext_vcpucontext_out;
   92.38 +
   92.39 +        if ( domctl->cmd == XEN_DOMCTL_get_ext_vcpucontext )
   92.40 +        {
   92.41 +#ifdef __x86_64__
   92.42 +            evc->sysenter_callback_cs      = v->arch.sysenter_callback_cs;
   92.43 +            evc->sysenter_callback_eip     = v->arch.sysenter_callback_eip;
   92.44 +            evc->sysenter_disables_events  = v->arch.sysenter_disables_events;
   92.45 +            evc->syscall32_callback_cs     = v->arch.syscall32_callback_cs;
   92.46 +            evc->syscall32_callback_eip    = v->arch.syscall32_callback_eip;
   92.47 +            evc->syscall32_disables_events = v->arch.syscall32_disables_events;
   92.48 +#else
   92.49 +            evc->sysenter_callback_cs      = 0;
   92.50 +            evc->sysenter_callback_eip     = 0;
   92.51 +            evc->sysenter_disables_events  = 0;
   92.52 +            evc->syscall32_callback_cs     = 0;
   92.53 +            evc->syscall32_callback_eip    = 0;
   92.54 +            evc->syscall32_disables_events = 0;
   92.55 +#endif
   92.56 +        }
   92.57 +        else
   92.58 +        {
   92.59 +#ifdef __x86_64__
   92.60 +            fixup_guest_code_selector(d, evc->sysenter_callback_cs);
   92.61 +            v->arch.sysenter_callback_cs      = evc->sysenter_callback_cs;
   92.62 +            v->arch.sysenter_callback_eip     = evc->sysenter_callback_eip;
   92.63 +            v->arch.sysenter_disables_events  = evc->sysenter_disables_events;
   92.64 +            fixup_guest_code_selector(d, evc->syscall32_callback_cs);
   92.65 +            v->arch.syscall32_callback_cs     = evc->syscall32_callback_cs;
   92.66 +            v->arch.syscall32_callback_eip    = evc->syscall32_callback_eip;
   92.67 +            v->arch.syscall32_disables_events = evc->syscall32_disables_events;
   92.68 +#else
   92.69 +            /* We do not support syscall/syscall32/sysenter on 32-bit Xen. */
   92.70 +            ret = -EINVAL;
   92.71 +            if ( (evc->sysenter_callback_cs & ~3) ||
   92.72 +                 evc->sysenter_callback_eip ||
   92.73 +                 (evc->syscall32_callback_cs & ~3) ||
   92.74 +                 evc->syscall32_callback_eip )
   92.75 +                goto ext_vcpucontext_out;
   92.76 +#endif
   92.77 +        }
   92.78 +
   92.79 +        ret = 0;
   92.80 +
   92.81 +    ext_vcpucontext_out:
   92.82 +        rcu_unlock_domain(d);
   92.83 +        if ( copy_to_guest(u_domctl, domctl, 1) )
   92.84 +            ret = -EFAULT;
   92.85 +    }
   92.86 +    break;
   92.87 +
   92.88      default:
   92.89          ret = -ENOSYS;
   92.90          break;
   92.91 @@ -728,24 +800,11 @@ void arch_get_info_guest(struct vcpu *v,
   92.92  
   92.93      if ( is_hvm_vcpu(v) )
   92.94      {
   92.95 -        if ( !is_pv_32on64_domain(v->domain) )
   92.96 -        {
   92.97 -            memset(c.nat->ctrlreg, 0, sizeof(c.nat->ctrlreg));
   92.98 -            c.nat->ctrlreg[0] = v->arch.hvm_vcpu.guest_cr[0];
   92.99 -            c.nat->ctrlreg[2] = v->arch.hvm_vcpu.guest_cr[2];
  92.100 -            c.nat->ctrlreg[3] = v->arch.hvm_vcpu.guest_cr[3];
  92.101 -            c.nat->ctrlreg[4] = v->arch.hvm_vcpu.guest_cr[4];
  92.102 -        }
  92.103 -#ifdef CONFIG_COMPAT
  92.104 -        else
  92.105 -        {
  92.106 -            memset(c.cmp->ctrlreg, 0, sizeof(c.cmp->ctrlreg));
  92.107 -            c.cmp->ctrlreg[0] = v->arch.hvm_vcpu.guest_cr[0];
  92.108 -            c.cmp->ctrlreg[2] = v->arch.hvm_vcpu.guest_cr[2];
  92.109 -            c.cmp->ctrlreg[3] = v->arch.hvm_vcpu.guest_cr[3];
  92.110 -            c.cmp->ctrlreg[4] = v->arch.hvm_vcpu.guest_cr[4];
  92.111 -        }
  92.112 -#endif
  92.113 +        memset(c.nat->ctrlreg, 0, sizeof(c.nat->ctrlreg));
  92.114 +        c.nat->ctrlreg[0] = v->arch.hvm_vcpu.guest_cr[0];
  92.115 +        c.nat->ctrlreg[2] = v->arch.hvm_vcpu.guest_cr[2];
  92.116 +        c.nat->ctrlreg[3] = v->arch.hvm_vcpu.guest_cr[3];
  92.117 +        c.nat->ctrlreg[4] = v->arch.hvm_vcpu.guest_cr[4];
  92.118      }
  92.119      else
  92.120      {
    93.1 --- a/xen/arch/x86/flushtlb.c	Tue Oct 30 11:33:55 2007 -0600
    93.2 +++ b/xen/arch/x86/flushtlb.c	Tue Oct 30 15:34:44 2007 -0600
    93.3 @@ -83,9 +83,12 @@ void write_cr3(unsigned long cr3)
    93.4      hvm_flush_guest_tlbs();
    93.5  
    93.6  #ifdef USER_MAPPINGS_ARE_GLOBAL
    93.7 -    __pge_off();
    93.8 -    asm volatile ( "mov %0, %%cr3" : : "r" (cr3) : "memory" );
    93.9 -    __pge_on();
   93.10 +    {
   93.11 +        unsigned long cr4 = read_cr4();
   93.12 +        write_cr4(cr4 & ~X86_CR4_PGE);
   93.13 +        asm volatile ( "mov %0, %%cr3" : : "r" (cr3) : "memory" );
   93.14 +        write_cr4(cr4);
   93.15 +    }
   93.16  #else
   93.17      asm volatile ( "mov %0, %%cr3" : : "r" (cr3) : "memory" );
   93.18  #endif
   93.19 @@ -98,17 +101,15 @@ void write_cr3(unsigned long cr3)
   93.20  void flush_area_local(const void *va, unsigned int flags)
   93.21  {
   93.22      const struct cpuinfo_x86 *c = &current_cpu_data;
   93.23 -    unsigned int level = flags & FLUSH_LEVEL_MASK;
   93.24 +    unsigned int order = (flags - 1) & FLUSH_ORDER_MASK;
   93.25      unsigned long irqfl;
   93.26  
   93.27 -    ASSERT(level < CONFIG_PAGING_LEVELS);
   93.28 -
   93.29      /* This non-reentrant function is sometimes called in interrupt context. */
   93.30      local_irq_save(irqfl);
   93.31  
   93.32      if ( flags & (FLUSH_TLB|FLUSH_TLB_GLOBAL) )
   93.33      {
   93.34 -        if ( level == 1 )
   93.35 +        if ( order == 0 )
   93.36          {
   93.37              /*
   93.38               * We don't INVLPG multi-page regions because the 2M/4M/1G
   93.39 @@ -126,8 +127,7 @@ void flush_area_local(const void *va, un
   93.40              hvm_flush_guest_tlbs();
   93.41  
   93.42  #ifndef USER_MAPPINGS_ARE_GLOBAL
   93.43 -            if ( !(flags & FLUSH_TLB_GLOBAL) ||
   93.44 -                 !(mmu_cr4_features & X86_CR4_PGE) )
   93.45 +            if ( !(flags & FLUSH_TLB_GLOBAL) || !(read_cr4() & X86_CR4_PGE) )
   93.46              {
   93.47                  asm volatile ( "mov %0, %%cr3"
   93.48                                 : : "r" (read_cr3()) : "memory" );
   93.49 @@ -135,9 +135,10 @@ void flush_area_local(const void *va, un
   93.50              else
   93.51  #endif
   93.52              {
   93.53 -                __pge_off();
   93.54 +                unsigned long cr4 = read_cr4();
   93.55 +                write_cr4(cr4 & ~X86_CR4_PGE);
   93.56                  barrier();
   93.57 -                __pge_on();
   93.58 +                write_cr4(cr4);
   93.59              }
   93.60  
   93.61              post_flush(t);
   93.62 @@ -146,14 +147,14 @@ void flush_area_local(const void *va, un
   93.63  
   93.64      if ( flags & FLUSH_CACHE )
   93.65      {
   93.66 -        unsigned long i, sz;
   93.67 -
   93.68 -        sz = level ? (1UL << ((level - 1) * PAGETABLE_ORDER)) : ULONG_MAX;
   93.69 +        unsigned long i, sz = 0;
   93.70  
   93.71 -        if ( c->x86_clflush_size && c->x86_cache_size &&
   93.72 -             (sz < (c->x86_cache_size >> (PAGE_SHIFT - 10))) )
   93.73 +        if ( order < (BITS_PER_LONG - PAGE_SHIFT - 1) )
   93.74 +            sz = 1UL << (order + PAGE_SHIFT);
   93.75 +
   93.76 +        if ( c->x86_clflush_size && c->x86_cache_size && sz &&
   93.77 +             ((sz >> 10) < c->x86_cache_size) )
   93.78          {