[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID 2b815d9acdea512cf50e7fbb3c5490590e85dbd5 # Parent 26dae1c72cd921d3194fde80ac9825d4e5b59ca9 # Parent 8e55c5c1147589b7a6a1875384d4317aec7ccf84 merge with xen-unstable.hg --- Makefile | 1 buildconfigs/Rules.mk | 7 buildconfigs/linux-defconfig_xen_x86_32 | 1 buildconfigs/linux-defconfig_xen_x86_64 | 1 buildconfigs/mk.linux-2.6-xen | 8 docs/man/xm.pod.1 | 93 - docs/misc/vtpm.txt | 47 docs/src/user.tex | 502 +++++ extras/mini-os/console/xencons_ring.c | 5 extras/mini-os/events.c | 84 extras/mini-os/gnttab.c | 158 + extras/mini-os/include/events.h | 24 extras/mini-os/include/gnttab.h | 14 extras/mini-os/include/lib.h | 13 extras/mini-os/include/mm.h | 8 extras/mini-os/include/os.h | 57 extras/mini-os/include/xenbus.h | 29 extras/mini-os/kernel.c | 9 extras/mini-os/lib/string.c | 10 extras/mini-os/mm.c | 125 + extras/mini-os/time.c | 6 extras/mini-os/xenbus/xenbus.c | 106 - linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c | 1 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 7 linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c | 12 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c | 29 linux-2.6-xen-sparse/drivers/char/tpm/Kconfig | 13 linux-2.6-xen-sparse/drivers/char/tpm/Makefile | 1 linux-2.6-xen-sparse/drivers/char/tpm/tpm.c | 873 ++++++++-- linux-2.6-xen-sparse/drivers/char/tpm/tpm.h | 74 linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c | 183 +- linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h | 42 linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c | 60 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c | 42 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 83 linux-2.6-xen-sparse/drivers/xen/console/console.c | 35 linux-2.6-xen-sparse/drivers/xen/core/evtchn.c | 5 linux-2.6-xen-sparse/drivers/xen/core/gnttab.c | 4 linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c | 39 linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 83 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 7 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 61 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c | 71 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h | 2 linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h | 2 patches/linux-2.6.16.13/fix-hz-suspend.patch | 9 patches/linux-2.6.16.13/net-gso.patch | 8 patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch | 704 ++++++++ patches/linux-2.6.16.13/xenoprof-generic.patch | 9 tools/examples/Makefile | 2 tools/examples/vtpm-addtodb | 10 tools/examples/vtpm-common.sh | 13 tools/firmware/hvmloader/Makefile | 6 tools/firmware/hvmloader/acpi_madt.c | 2 tools/firmware/hvmloader/hvmloader.c | 8 tools/firmware/hvmloader/mp_tables.c | 426 ++++ tools/firmware/rombios/Makefile | 36 tools/firmware/rombios/rombios.c | 30 tools/ioemu/hw/piix4acpi.c | 2 tools/libxc/xc_hvm_build.c | 9 tools/libxc/xc_linux_build.c | 20 tools/libxc/xc_linux_save.c | 23 tools/libxc/xc_load_elf.c | 29 tools/libxc/xc_private.c | 2 tools/libxc/xg_private.h | 14 tools/python/xen/xend/XendLogging.py | 2 tools/python/xen/xm/cfgbootpolicy.py | 2 tools/python/xen/xm/create.py | 3 tools/python/xen/xm/dumppolicy.py | 4 tools/python/xen/xm/labels.py | 3 tools/python/xen/xm/loadpolicy.py | 4 tools/python/xen/xm/main.py | 2 tools/python/xen/xm/makepolicy.py | 4 tools/python/xen/xm/shutdown.py | 5 tools/xenmon/xenmon.py | 26 tools/xenstat/libxenstat/src/xenstat.c | 174 + tools/xenstat/libxenstat/src/xenstat.h | 22 tools/xenstat/xentop/xentop.c | 152 + tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py | 11 tools/xm-test/tests/vtpm/03_vtpm-susp_res.py | 94 - tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py | 24 tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py | 24 tools/xm-test/tests/vtpm/06_vtpm-susp_res_pcrs.py | 139 + tools/xm-test/tests/vtpm/07_vtpm-mig_pcrs.py | 132 + tools/xm-test/tests/vtpm/08_vtpm-mig_pcrs.py | 132 + tools/xm-test/tests/vtpm/Makefile.am | 5 tools/xm-test/tests/vtpm/vtpm_utils.py | 2 xen/arch/ia64/xen/dom0_ops.c | 2 xen/arch/ia64/xen/xensetup.c | 10 xen/arch/x86/dom0_ops.c | 14 xen/arch/x86/domain.c | 9 xen/arch/x86/hvm/svm/svm.c | 99 - xen/arch/x86/hvm/vmx/vmcs.c | 216 +- xen/arch/x86/hvm/vmx/vmx.c | 176 +- xen/arch/x86/setup.c | 11 xen/arch/x86/shadow.c | 12 xen/arch/x86/smpboot.c | 3 xen/arch/x86/traps.c | 35 xen/arch/x86/x86_emulate.c | 2 xen/common/dom0_ops.c | 100 - xen/common/domain.c | 98 - xen/common/elf.c | 23 xen/common/event_channel.c | 7 xen/common/grant_table.c | 12 xen/common/memory.c | 9 xen/common/page_alloc.c | 4 xen/common/sched_credit.c | 7 xen/common/sched_sedf.c | 2 xen/common/schedule.c | 21 xen/common/softirq.c | 16 xen/common/timer.c | 9 xen/drivers/char/console.c | 14 xen/include/asm-ia64/grant_table.h | 5 xen/include/asm-x86/grant_table.h | 5 xen/include/asm-x86/hvm/vmx/vmcs.h | 15 xen/include/asm-x86/hvm/vmx/vmx.h | 5 xen/include/asm-x86/processor.h | 3 xen/include/public/arch-ia64.h | 2 xen/include/public/arch-x86_32.h | 2 xen/include/public/arch-x86_64.h | 2 xen/include/public/dom0_ops.h | 10 xen/include/public/io/netif.h | 62 xen/include/public/memory.h | 12 xen/include/xen/lib.h | 18 xen/include/xen/sched.h | 25 xen/include/xen/timer.h | 6 126 files changed, 5244 insertions(+), 1204 deletions(-) diff -r 26dae1c72cd9 -r 2b815d9acdea Makefile --- a/Makefile Wed Jul 05 10:23:54 2006 -0600 +++ b/Makefile Wed Jul 05 20:11:37 2006 -0600 @@ -130,6 +130,7 @@ distclean: rm -rf dist patches/tmp for i in $(ALLKERNELS) ; do $(MAKE) $$i-delete ; done for i in $(ALLSPARSETREES) ; do $(MAKE) $$i-mrproper ; done + rm -rf patches/*/.makedep # Linux name for GNU distclean .PHONY: mrproper diff -r 26dae1c72cd9 -r 2b815d9acdea buildconfigs/Rules.mk --- a/buildconfigs/Rules.mk Wed Jul 05 10:23:54 2006 -0600 +++ b/buildconfigs/Rules.mk Wed Jul 05 20:11:37 2006 -0600 @@ -59,10 +59,6 @@ ifneq ($(PATCHDIRS),) $(patsubst patches/%,patches/%/.makedep,$(PATCHDIRS)): patches/%/.makedep: @echo 'ref-$*/.valid-ref: $$(wildcard patches/$*/*.patch)' >$@ -.PHONY: clean -clean:: - rm -f patches/*/.makedep - ref-%/.valid-ref: pristine-%/.valid-pristine set -e rm -rf $(@D) @@ -111,7 +107,8 @@ linux-2.6-xen.patch: ref-linux-$(LINUX_V rm -rf tmp-$@ %-mrproper: - rm -rf pristine-$(*)* ref-$(*)* $*.tar.bz2 + $(MAKE) -f buildconfigs/mk.$*-xen mrpropper + rm -rf pristine-$(*)* ref-$(*)* rm -rf $*-xen.patch .PHONY: config-update-pae diff -r 26dae1c72cd9 -r 2b815d9acdea buildconfigs/linux-defconfig_xen_x86_32 --- a/buildconfigs/linux-defconfig_xen_x86_32 Wed Jul 05 10:23:54 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Wed Jul 05 20:11:37 2006 -0600 @@ -1902,6 +1902,7 @@ CONFIG_HANGCHECK_TIMER=m # TPM devices # CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m CONFIG_TCG_INFINEON=m diff -r 26dae1c72cd9 -r 2b815d9acdea buildconfigs/linux-defconfig_xen_x86_64 --- a/buildconfigs/linux-defconfig_xen_x86_64 Wed Jul 05 10:23:54 2006 -0600 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Wed Jul 05 20:11:37 2006 -0600 @@ -1765,6 +1765,7 @@ CONFIG_HANGCHECK_TIMER=m # TPM devices # CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m CONFIG_TCG_NSC=m CONFIG_TCG_ATMEL=m CONFIG_TCG_INFINEON=m diff -r 26dae1c72cd9 -r 2b815d9acdea buildconfigs/mk.linux-2.6-xen --- a/buildconfigs/mk.linux-2.6-xen Wed Jul 05 10:23:54 2006 -0600 +++ b/buildconfigs/mk.linux-2.6-xen Wed Jul 05 20:11:37 2006 -0600 @@ -47,8 +47,14 @@ config: $(LINUX_DIR)/include/linux/autoc .PHONY: clean clean:: - $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean + [ ! -d $(LINUX_DIR) ] || \ + $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean + .PHONY: delete delete: rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR) + +.PHONY: mrpropper +mrpropper: + rm -f linux-$(LINUX_VER).tar.bz2 diff -r 26dae1c72cd9 -r 2b815d9acdea docs/man/xm.pod.1 --- a/docs/man/xm.pod.1 Wed Jul 05 10:23:54 2006 -0600 +++ b/docs/man/xm.pod.1 Wed Jul 05 20:11:37 2006 -0600 @@ -875,13 +875,42 @@ the currently enforced access control po the currently enforced access control policy. The default for I<type> is 'dom'. The labels are arranged in alphabetical order. -=item B<addlabel> I<configfile> I<label> [I<policy>] +=item B<addlabel> I<label> dom I<configfile> [I<policy>] + +=item B<addlabel> I<label> res I<resource> [I<policy>] Adds the security label with name I<label> to a domain -I<configfile>. Unless specified, the default I<policy> is the +I<configfile> (dom) or to the global resource label file for the +given I<resource> (res). Unless specified, the default I<policy> is the currently enforced access control policy. This subcommand also verifies that the I<policy> definition supports the specified I<label> name. + +=item B<rmlabel> dom I<configfile> + +=item B<rmlabel> res I<resource> + +Works the same as the I<addlabel> command (above), except that this +command will remove the label from the domain I<configfile> (dom) or +the global resource label file (res). + +=item B<getlabel> dom I<configfile> + +=item B<getlabel> res I<resource> + +Shows the label for the given I<configfile> or I<resource> + +=item B<resources> + +Lists all resources in the global resource label file. Each resource +is listed with its associated label and policy name. + +=item B<dry-run> I<configfile> + +Determines if the specified I<configfile> describes a domain with a valid +security configuration for type enforcement. The test shows the policy +decision made for each resource label against the domain label as well as +the overall decision. B<CONFIGURING SECURITY> @@ -960,17 +989,18 @@ B<ATTACHING A SECURITY LABEL TO A DOMAIN =over 4 -This subcommand attaches a security label to a domain configuration -file, here a HomeBanking label. The example policy ensures that this -domain does not share information with other non-hombanking user -domains (i.e., domains labeled as dom_Fun or dom_Boinc) and that it -will not run simultaneously with domains labeled as dom_Fun. +The I<addlabel> subcommand can attach a security label to a domain +configuration file, here a HomeBanking label. The example policy +ensures that this domain does not share information with other +non-hombanking user domains (i.e., domains labeled as dom_Fun or +dom_Boinc) and that it will not run simultaneously with domains +labeled as dom_Fun. We assume that the specified myconfig.xm configuration file actually instantiates a domain that runs workloads related to home-banking, probably just a browser environment for online-banking. - xm addlabel myconfig.xm dom_HomeBanking + xm addlabel dom_HomeBanking dom myconfig.xm The very simple configuration file might now look as printed below. The I<addlabel> subcommand added the B<access_control> entry at @@ -997,6 +1027,38 @@ permitted". =back +B<ATTACHING A SECURITY LABEL TO A RESOURCE> + +=over 4 + +The I<addlabel> subcommand can also be used to attach a security +label to a resource. Following the home banking example from above, +we can label a disk resource (e.g., a physical partition or a file) +to make it accessible to the home banking domain. The example policy +provides a resource label, res_LogicalDiskPartition1(hda1), that is +compatible with the HomeBanking domain label. + + xm addlabel "res_LogicalDiskPartition1(hda1)" res phy:hda6 + +After labeling this disk resource, it can be attached to the domain +by adding a line to the domain configuration file. The line below +attaches this disk to the domain at boot time. + + disk = [ 'phy:hda6,sda2,w' ] + +Alternatively, the resource can be attached after booting the domain +by using the I<block-attach> subcommand. + + xm block-attach homebanking phy:hda6 sda2 w + +Note that labeled resources cannot be used when security is turned +off. Any attempt to use labeled resources with security turned off +will result in a failure with a corresponding error message. The +solution is to enable security or, if security is no longer desired, +to remove the resource label using the I<rmlabel> subcommand. + +=back + B<STARTING AND LISTING LABELED DOMAINS> =over 4 @@ -1008,6 +1070,21 @@ B<STARTING AND LISTING LABELED DOMAINS> Name ID ... Time(s) Label homebanking 23 ... 4.4 dom_HomeBanking Domain-0 0 ... 2658.8 dom_SystemManagement + +=back + +B<LISTING LABELED RESOURCES> + +=over 4 + + xm resources + + phy:hda6 + policy: example.chwall_ste.client_v1 + label: res_LogicalDiskPartition1(hda1) + file:/xen/disk_image/disk.img + policy: example.chwall_ste.client_v1 + label: res_LogicalDiskPartition2(hda2) =back diff -r 26dae1c72cd9 -r 2b815d9acdea docs/misc/vtpm.txt --- a/docs/misc/vtpm.txt Wed Jul 05 10:23:54 2006 -0600 +++ b/docs/misc/vtpm.txt Wed Jul 05 20:11:37 2006 -0600 @@ -1,5 +1,5 @@ Copyright: IBM Corporation (C), Intel Co Copyright: IBM Corporation (C), Intel Corporation -17 August 2005 +29 June 2006 Authors: Stefan Berger <stefanb@xxxxxxxxxx> (IBM), Employees of Intel Corp @@ -9,23 +9,33 @@ that the user is fairly familiar with co that the user is fairly familiar with compiling and installing XEN and Linux on a machine. -Production Prerequisites: An x86-based machine machine with an ATMEL or -National Semiconductor (NSC) TPM on the motherboard. +Production Prerequisites: An x86-based machine machine with a +Linux-supported TPM on the motherboard (NSC, Atmel, Infineon, TPM V1.2). Development Prerequisites: An emulator for TESTING ONLY is provided -Compiling XEN tree: -------------------- +Compiling the XEN tree: +----------------------- Compile the XEN tree as usual after the following lines set in the linux-2.6.??-xen/.config file: -CONFIG_XEN_TPMDEV_BACKEND=y +CONFIG_XEN_TPMDEV_BACKEND=m + +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m (supported after 2.6.17-rc4) +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_XEN=m +<possible other TPM drivers supported by Linux> + +If the frontend driver needs to be compiled into the user domain +kernel, then the following two lines should be changed. CONFIG_TCG_TPM=y -CONFIG_TCG_NSC=m -CONFIG_TCG_ATMEL=m CONFIG_TCG_XEN=y + You must also enable the virtual TPM to be built: @@ -63,7 +73,7 @@ available. It works similar to making a available. It works similar to making a network interface available to a domain. -kernel = "/boot/vmlinuz-2.6.12-xenU" +kernel = "/boot/vmlinuz-2.6.x" ramdisk = "/xen/initrd_domU/U1_ramdisk.img" memory = 32 name = "TPMUserDomain0" @@ -92,7 +102,7 @@ Running the TPM: Running the TPM: ---------------- -To run the vTPM, dev device /dev/vtpm must be available. +To run the vTPM, the device /dev/vtpm must be available. Verify that 'ls -l /dev/vtpm' shows the following output: crw------- 1 root root 10, 225 Aug 11 06:58 /dev/vtpm @@ -101,16 +111,26 @@ mknod /dev/vtpm c 10 225 mknod /dev/vtpm c 10 225 Make sure that the vTPM is running in domain 0. To do this run the -following +following: + +modprobe tpmbk /usr/bin/vtpm_managerd Start a user domain using the 'xm create' command. Once you are in the -shell of the user domain, you should be able to do the following: +shell of the user domain, you should be able to do the following as +user 'root': -> cd /sys/devices/vtpm +Insert the TPM frontend into the kernel if it has been compiled as a +kernel module. + +> modprobe tpm_xenu + +Check the status of the TPM + +> cd /sys/devices/xen/vtpm-0 > ls -cancel caps pcrs pubek +[...] cancel caps pcrs pubek [...] > cat pcrs PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 PCR-01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 diff -r 26dae1c72cd9 -r 2b815d9acdea docs/src/user.tex --- a/docs/src/user.tex Wed Jul 05 10:23:54 2006 -0600 +++ b/docs/src/user.tex Wed Jul 05 20:11:37 2006 -0600 @@ -2203,6 +2203,33 @@ ne2000 & Enable ne2000, default = serial & Enable redirection of VMX serial output to pty device\\ +\end{tabular} + +\begin{tabular}{lp{10cm}} + +usb & Enable USB support without defining a specific USB device. +This option defaults to 0 (disabled) unless the option usbdevice is +specified in which case this option then defaults to 1 (enabled).\\ + +usbdevice & Enable USB support and also enable support for the given +device. Devices that can be specified are {\small {\tt mouse}} (a PS/2 style +mouse), {\small {\tt tablet}} (an absolute pointing device) and +{\small {\tt host:id1:id2}} (a physical USB device on the host machine whose +ids are {\small {\tt id1}} and {\small {\tt id2}}). The advantage +of {\small {\tt tablet}} is that Windows guests will automatically recognize +and support this device so specifying the config line + +{\small +\begin{verbatim} + usbdevice='tablet' +\end{verbatim} +} + +will create a mouse that works transparently with Windows guests under VNC. +Linux doesn't recognize the USB tablet yet so Linux guests under VNC will +still need the Summagraphics emulation. +Details about mouse emulation are provided in section \textbf{A.4.3}.\\ + localtime & Set the real time clock to local time [default=0, that is, set to UTC].\\ enable-audio & Enable audio support. This is under development.\\ @@ -2317,29 +2344,458 @@ Simply follow the usual method of creati In the default configuration, VNC is on and SDL is off. Therefore VNC windows will open when VMX guests are created. If you want to use SDL to create VMX guests, set {\small {\tt sdl=1}} in your VMX configuration file. You can also turn off VNC by setting {\small {\tt vnc=0}}. -\subsection{Use mouse in VNC window} -The default PS/2 mouse will not work properly in VMX by a VNC window. Summagraphics mouse emulation does work in this environment. A Summagraphics mouse can be enabled by reconfiguring 2 services: - -{\small {\tt 1. General Purpose Mouse (GPM). The GPM daemon is configured in different ways in different Linux distributions. On a Redhat distribution, this is accomplished by changing the file `/etc/sysconfig/mouse' to have the following:\\ -MOUSETYPE="summa"\\ -XMOUSETYPE="SUMMA"\\ -DEVICE=/dev/ttyS0\\ -\\ -2. X11. For all Linux distributions, change the Mouse0 stanza in `/etc/X11/xorg.conf' to:\\ -Section "InputDevice"\\ -Identifier "Mouse0"\\ -Driver "summa"\\ -Option "Device" "/dev/ttyS0"\\ -Option "InputFashion" "Tablet"\\ -Option "Mode" "Absolute"\\ -Option "Name" "EasyPen"\\ -Option "Compatible" "True"\\ -Option "Protocol" "Auto"\\ -Option "SendCoreEvents" "on"\\ -Option "Vendor" "GENIUS"\\ -EndSection}} - -If the Summagraphics mouse isn't the default mouse, you can manually kill 'gpm' and restart it with the command "gpm -m /dev/ttyS0 -t summa". Note that Summagraphics mouse makes no sense in an SDL window and is therefore not available in this environment. +\subsection{Mouse issues, especially under VNC} +Mouse handling when using VNC is a little problematic. +The problem is that the VNC viewer provides a virtual pointer which is +located at an absolute location in the VNC window and only absolute +coordinates are provided. +The VMX device model converts these absolute mouse coordinates +into the relative motion deltas that are expected by the PS/2 +mouse driver running in the guest. +Unfortunately, +it is impossible to keep these generated mouse deltas +accurate enough for the guest cursor to exactly match +the VNC pointer. +This can lead to situations where the guest's cursor +is in the center of the screen and there's no way to +move that cursor to the left +(it can happen that the VNC pointer is at the left +edge of the screen and, +therefore, +there are no longer any left mouse deltas that +can be provided by the device model emulation code.) + +To deal with these mouse issues there are 4 different +mouse emulations available from the VMX device model: + +\begin{description} +\item[PS/2 mouse over the PS/2 port.] +This is the default mouse +that works perfectly well under SDL. +Under VNC the guest cursor will get +out of sync with the VNC pointer. +When this happens you can re-synchronize +the guest cursor to the VNC pointer by +holding down the +\textbf{left-ctl} +and +\textbf{left-alt} +keys together. +While these keys are down VNC pointer motions +will not be reported to the guest so +that the VNC pointer can be moved +to a place where it is possible +to move the guest cursor again. + +\item[Summagraphics mouse over the serial port.] +The device model also provides emulation +for a Summagraphics tablet, +an absolute pointer device. +This emulation is provided over the second +serial port, +\textbf{/dev/ttyS1} +for Linux guests and +\textbf{COM2} +for Windows guests. +Unfortunately, +neither Linux nor Windows provides +default support for the Summagraphics +tablet so the guest will have to be +manually configured for this mouse. + +\textbf{Linux configuration.} + +First, +configure the GPM service to use the Summagraphics tablet. +This can vary between distributions but, +typically, +all that needs to be done is modify the file +\path{/etc/sysconfig/mouse} to contain the lines: + +{\small +\begin{verbatim} + MOUSETYPE="summa" + XMOUSETYPE="SUMMA" + DEVICE=/dev/ttyS1 +\end{verbatim} +} + +and then restart the GPM daemon. + +Next, +modify the X11 config +\path{/etc/X11/xorg.conf} +to support the Summgraphics tablet by replacing +the input device stanza with the following: + +{\small +\begin{verbatim} + Section "InputDevice" + Identifier "Mouse0" + Driver "summa" + Option "Device" "/dev/ttyS1" + Option "InputFashion" "Tablet" + Option "Mode" "Absolute" + Option "Name" "EasyPen" + Option "Compatible" "True" + Option "Protocol" "Auto" + Option "SendCoreEvents" "on" + Option "Vendor" "GENIUS" + EndSection +\end{verbatim} +} + +Restart X and the X cursor should now properly +track the VNC pointer. + + +\textbf{Windows configuration.} + +Get the file +\path{http://www.cad-plan.de/files/download/tw2k.exe} +and execute that file on the guest, +answering the questions as follows: + +\begin{enumerate} +\item When the program asks for \textbf{model}, +scroll down and selese \textbf{SummaSketch (MM Compatible)}. + +\item When the program asks for \textbf{COM Port} specify \textbf{com2}. + +\item When the programs asks for a \textbf{Cursor Type} specify +\textbf{4 button cursor/puck}. + +\item The guest system will then reboot and, +when it comes back up, +the guest cursor will now properly track +the VNC pointer. +\end{enumerate} + +\item[PS/2 mouse over USB port.] +This is just the same PS/2 emulation except it is +provided over a USB port. +This emulation is enabled by the configuration flag: +{\small +\begin{verbatim} + usbdevice='mouse' +\end{verbatim} +} + +\item[USB tablet over USB port.] +The USB tablet is an absolute pointing device +that has the advantage that it is automatically +supported under Windows guests, +although Linux guests still require some +manual configuration. +This mouse emulation is enabled by the +configuration flag: +{\small +\begin{verbatim} + usbdevice='tablet' +\end{verbatim} +} + +\textbf{Linux configuration.} + +Unfortunately, +there is no GPM support for the +USB tablet at this point in time. +If you intend to use a GPM pointing +device under VNC you should +configure the guest for Summagraphics +emulation. + +Support for X11 is available by following +the instructions at\\ +\verb+http://stz-softwaretechnik.com/~ke/touchscreen/evtouch.html+\\ +with one minor change. +The +\path{xorg.conf} +given in those instructions +uses the wrong values for the X \& Y minimums and maximums, +use the following config stanza instead: + +{\small +\begin{verbatim} + Section "InputDevice" + Identifier "Tablet" + Driver "evtouch" + Option "Device" "/dev/input/event2" + Option "DeviceName" "touchscreen" + Option "MinX" "0" + Option "MinY" "0" + Option "MaxX" "32256" + Option "MaxY" "32256" + Option "ReportingMode" "Raw" + Option "Emulate3Buttons" + Option "Emulate3Timeout" "50" + Option "SendCoreEvents" "On" + EndSection +\end{verbatim} +} + +\textbf{Windows configuration.} + +Just enabling the USB tablet in the +guest's configuration file is sufficient, +Windows will automatically recognize and +configure device drivers for this +pointing device. + +\end{description} + +\subsection{USB Support} +There is support for an emulated USB mouse, +an emulated USB tablet +and physical low speed USB devices +(support for high speed USB 2.0 devices is +still under development). + +\begin{description} +\item[USB PS/2 style mouse.] +Details on the USB mouse emulation are +given in sections +\textbf{A.2} +and +\textbf{A.4.3}. +Enabling USB PS/2 style mouse emulation +is just a matter of adding the line + +{\small +\begin{verbatim} + usbdevice='mouse' +\end{verbatim} +} + +to the configuration file. +\item[USB tablet.] +Details on the USB tablet emulation are +given in sections +\textbf{A.2} +and +\textbf{A.4.3}. +Enabling USB tablet emulation +is just a matter of adding the line + +{\small +\begin{verbatim} + usbdevice='tablet' +\end{verbatim} +} + +to the configuration file. +\item[USB physical devices.] +Access to a physical (low speed) USB device +is enabled by adding a line of the form + +{\small +\begin{verbatim} + usbdevice='host:vid:pid' +\end{verbatim} +} + +into the the configuration file.\footnote{ +There is an alternate +way of specifying a USB device that +uses the syntax +\textbf{host:bus.addr} +but this syntax suffers from +a major problem that makes +it effectively useless. +The problem is that the +\textbf{addr} +portion of this address +changes every time the USB device +is plugged into the system. +For this reason this addressing +scheme is not recommended and +will not be documented further. +} +\textbf{vid} +and +\textbf{pid} +are a +product id and +vendor id +that uniquely identify +the USB device. +These ids can be identified +in two ways: + +\begin{enumerate} +\item Through the control window. +As described in section +\textbf{A.4.6} +the control window +is activated by pressing +\textbf{ctl-alt-2} +in the guest VGA window. +As long as USB support is +enabled in the guest by including +the config file line +{\small +\begin{verbatim} + usb=1 +\end{verbatim} +} +then executing the command +{\small +\begin{verbatim} + info usbhost +\end{verbatim} +} +in the control window +will display a list of all +usb devices and their ids. +For example, +this output: +{\small +\begin{verbatim} + Device 1.3, speed 1.5 Mb/s + Class 00: USB device 04b3:310b +\end{verbatim} +} +was created from a USB mouse with +vendor id +\textbf{04b3} +and product id +\textbf{310b}. +This device could be made available +to the VMX guest by including the +config file entry +{\small +\begin{verbatim} + usbdevice='host:04be:310b' +\end{verbatim} +} + +It is also possible to +enable access to a USB +device dynamically through +the control window. +The control window command +{\small +\begin{verbatim} + usb_add host:vid:pid +\end{verbatim} +} +will also allow access to a +USB device with vendor id +\textbf{vid} +and product id +\textbf{pid}. +\item Through the +\path{/proc} file system. +The contents of the pseudo file +\path{/proc/bus/usb/devices} +can also be used to identify +vendor and product ids. +Looking at this file, +the line starting with +\textbf{P:} +has a field +\textbf{Vendor} +giving the vendor id and +another field +\textbf{ProdID} +giving the product id. +The contents of +\path{/proc/bus/usb/devices} +for the example mouse is as +follows: +{\small +\begin{verbatim} +T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=1.5 MxCh= 0 +D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +P: Vendor=04b3 ProdID=310b Rev= 1.60 +C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=(none) +E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=10ms +\end{verbatim} +} +Note that the +\textbf{P:} +line correctly identifies the +vendor id and product id +for this mouse as +\textbf{04b3:310b}. +\end{enumerate} +There is one other issue to +be aware of when accessing a +physical USB device from the guest. +The Dom0 kernel must not have +a device driver loaded for +the device that the guest wishes +to access. +This means that the Dom0 +kernel must not have that +device driver compiled into +the kernel or, +if using modules, +that driver module must +not be loaded. +Note that this is the device +specific USB driver that must +not be loaded, +either the +\textbf{UHCI} +or +\textbf{OHCI} +USB controller driver must +still be loaded. + +Going back to the USB mouse +as an example, +if \textbf{lsmod} +gives the output: + +{\small +\begin{verbatim} +Module Size Used by +usbmouse 4128 0 +usbhid 28996 0 +uhci_hcd 35409 0 +\end{verbatim} +} + +then the USB mouse is being +used by the Dom0 kernel and is +not available to the guest. +Executing the command +\textbf{rmmod usbhid}\footnote{ +Turns out the +\textbf{usbhid} +driver is the significant +one for the USB mouse, +the presence or absence of +the module +\textbf{usbmouse} +has no effect on whether or +not the guest can see a USB mouse.} +will remove the USB mouse +driver from the Dom0 kernel +and the mouse will now be +accessible by the VMX guest. + +Be aware the the Linux USB +hotplug system will reload +the drivers if a USB device +is removed and plugged back +in. +This means that just unloading +the driver module might not +be sufficient if the USB device +is removed and added back. +A more reliable technique is +to first +\textbf{rmmod} +the driver and then rename the +driver file in the +\path{/lib/modules} +directory, +just to make sure it doesn't get +reloaded. +\end{description} \subsection{Destroy VMX guests} VMX guests can be destroyed in the same way as can paravirtualized guests. We recommend that you type the command diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/console/xencons_ring.c --- a/extras/mini-os/console/xencons_ring.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/console/xencons_ring.c Wed Jul 05 20:11:37 2006 -0600 @@ -53,7 +53,7 @@ int xencons_ring_send(const char *data, -static void handle_input(int port, struct pt_regs *regs) +static void handle_input(int port, struct pt_regs *regs, void *ign) { struct xencons_interface *intf = xencons_interface(); XENCONS_RING_IDX cons, prod; @@ -83,7 +83,8 @@ int xencons_ring_init(void) if (!start_info.console_evtchn) return 0; - err = bind_evtchn(start_info.console_evtchn, handle_input); + err = bind_evtchn(start_info.console_evtchn, handle_input, + NULL); if (err <= 0) { printk("XEN console request chn bind failed %i\n", err); return err; diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/events.c --- a/extras/mini-os/events.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/events.c Wed Jul 05 20:11:37 2006 -0600 @@ -22,9 +22,18 @@ #include <events.h> #include <lib.h> +#define NR_EVS 1024 + +/* this represents a event handler. Chaining or sharing is not allowed */ +typedef struct _ev_action_t { + void (*handler)(int, struct pt_regs *, void *); + void *data; + u32 count; +} ev_action_t; + static ev_action_t ev_actions[NR_EVS]; -void default_handler(int port, struct pt_regs *regs); +void default_handler(int port, struct pt_regs *regs, void *data); /* @@ -35,42 +44,33 @@ int do_event(u32 port, struct pt_regs *r ev_action_t *action; if (port >= NR_EVS) { printk("Port number too large: %d\n", port); - goto out; + goto out; } action = &ev_actions[port]; action->count++; - if (!action->handler) - { - printk("Spurious event on port %d\n", port); - goto out; - } - - if (action->status & EVS_DISABLED) - { - printk("Event on port %d disabled\n", port); - goto out; - } - /* call the handler */ - action->handler(port, regs); - + action->handler(port, regs, action->data); + out: clear_evtchn(port); + return 1; } -int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) ) +int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *, void *), + void *data ) { if(ev_actions[port].handler != default_handler) printk("WARN: Handler for port %d already registered, replacing\n", port); + ev_actions[port].data = data; + wmb(); ev_actions[port].handler = handler; - ev_actions[port].status &= ~EVS_DISABLED; - + /* Finally unmask the port */ unmask_evtchn(port); @@ -82,13 +82,14 @@ void unbind_evtchn( u32 port ) if (ev_actions[port].handler == default_handler) printk("WARN: No handler for port %d when unbinding\n", port); ev_actions[port].handler = default_handler; - ev_actions[port].status |= EVS_DISABLED; + wmb(); + ev_actions[port].data = NULL; } -int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) ) +int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data), + void *data) { evtchn_op_t op; - int ret = 0; /* Try to bind the virq to a port */ op.cmd = EVTCHNOP_bind_virq; @@ -97,13 +98,11 @@ int bind_virq( u32 virq, void (*handler) if ( HYPERVISOR_event_channel_op(&op) != 0 ) { - ret = 1; printk("Failed to bind virtual IRQ %d\n", virq); - goto out; + return 1; } - bind_evtchn(op.u.bind_virq.port, handler); -out: - return ret; + bind_evtchn(op.u.bind_virq.port, handler, data); + return 0; } void unbind_virq( u32 port ) @@ -137,13 +136,38 @@ void init_events(void) #endif /* inintialise event handler */ for ( i = 0; i < NR_EVS; i++ ) - { - ev_actions[i].status = EVS_DISABLED; + { ev_actions[i].handler = default_handler; mask_evtchn(i); } } -void default_handler(int port, struct pt_regs *regs) { +void default_handler(int port, struct pt_regs *regs, void *ignore) +{ printk("[Port %d] - event received\n", port); } + +/* Unfortunate confusion of terminology: the port is unbound as far + as Xen is concerned, but we automatically bind a handler to it + from inside mini-os. */ +int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs, + void *data), + void *data) +{ + u32 port; + evtchn_op_t op; + int err; + + op.cmd = EVTCHNOP_alloc_unbound; + op.u.alloc_unbound.dom = DOMID_SELF; + op.u.alloc_unbound.remote_dom = 0; + + err = HYPERVISOR_event_channel_op(&op); + if (err) { + printk("Failed to alloc unbound evtchn: %d.\n", err); + return -1; + } + port = op.u.alloc_unbound.port; + bind_evtchn(port, handler, data); + return port; +} diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/include/events.h --- a/extras/mini-os/include/events.h Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/include/events.h Wed Jul 05 20:11:37 2006 -0600 @@ -22,28 +22,18 @@ #include<traps.h> #include <xen/event_channel.h> -#define NR_EVS 1024 - -/* ev handler status */ -#define EVS_INPROGRESS 1 /* Event handler active - do not enter! */ -#define EVS_DISABLED 2 /* Event disabled - do not enter! */ -#define EVS_PENDING 4 /* Event pending - replay on enable */ -#define EVS_REPLAY 8 /* Event has been replayed but not acked yet */ - -/* this represents a event handler. Chaining or sharing is not allowed */ -typedef struct _ev_action_t { - void (*handler)(int, struct pt_regs *); - unsigned int status; /* IRQ status */ - u32 count; -} ev_action_t; - /* prototypes */ int do_event(u32 port, struct pt_regs *regs); -int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) ); -int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) ); +int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data), + void *data); +int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *, void *data), + void *data ); void unbind_evtchn( u32 port ); void init_events(void); void unbind_virq( u32 port ); +int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs, + void *data), + void *data); static inline int notify_remote_via_evtchn(int port) { diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/include/lib.h --- a/extras/mini-os/include/lib.h Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/include/lib.h Wed Jul 05 20:11:37 2006 -0600 @@ -89,6 +89,7 @@ char *strchr(const char *s, int c); char *strchr(const char *s, int c); char *strstr(const char *s1, const char *s2); char * strcat(char * dest, const char * src); +char *strdup(const char *s); #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -98,6 +99,18 @@ struct kvec { size_t iov_len; }; +#define ASSERT(x) \ +do { \ + if (!(x)) { \ + printk("ASSERTION FAILED: %s at %s:%d.\n", \ + # x , \ + __FILE__, \ + __LINE__); \ + BUG(); \ + } \ +} while(0) +/* Consistency check as much as possible. */ +void sanity_check(void); #endif /* _LIB_H_ */ diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/include/mm.h --- a/extras/mini-os/include/mm.h Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/include/mm.h Wed Jul 05 20:11:37 2006 -0600 @@ -196,9 +196,11 @@ static __inline__ paddr_t machine_to_phy #define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START)) #define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt))) +#define virt_to_mfn(_virt) (pfn_to_mfn(virt_to_pfn(_virt))) #define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach))) +#define virt_to_mach(_virt) (phys_to_machine(to_phys(_virt))) #define mfn_to_virt(_mfn) (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT)) -#define pfn_to_virt(_pfn) (to_virt(_pfn << PAGE_SHIFT)) +#define pfn_to_virt(_pfn) (to_virt((_pfn) << PAGE_SHIFT)) /* Pagetable walking. */ #define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT) @@ -206,7 +208,7 @@ static __inline__ paddr_t machine_to_phy void init_mm(void); unsigned long alloc_pages(int order); -#define alloc_page() alloc_pages(0); +#define alloc_page() alloc_pages(0) void free_pages(void *pointer, int order); static __inline__ int get_order(unsigned long size) @@ -219,4 +221,6 @@ static __inline__ int get_order(unsigned } +void *map_frames(unsigned long *f, unsigned long n); + #endif /* _MM_H_ */ diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/include/os.h --- a/extras/mini-os/include/os.h Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/include/os.h Wed Jul 05 20:11:37 2006 -0600 @@ -445,7 +445,62 @@ static __inline__ unsigned long __ffs(un /********************* common i386 and x86_64 ****************************/ - +struct __synch_xchg_dummy { unsigned long a[100]; }; +#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x)) + +#define synch_cmpxchg(ptr, old, new) \ +((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\ + (unsigned long)(old), \ + (unsigned long)(new), \ + sizeof(*(ptr)))) + +static inline unsigned long __synch_cmpxchg(volatile void *ptr, + unsigned long old, + unsigned long new, int size) +{ + unsigned long prev; + switch (size) { + case 1: + __asm__ __volatile__("lock; cmpxchgb %b1,%2" + : "=a"(prev) + : "q"(new), "m"(*__synch_xg(ptr)), + "0"(old) + : "memory"); + return prev; + case 2: + __asm__ __volatile__("lock; cmpxchgw %w1,%2" + : "=a"(prev) + : "r"(new), "m"(*__synch_xg(ptr)), + "0"(old) + : "memory"); + return prev; +#ifdef __x86_64__ + case 4: + __asm__ __volatile__("lock; cmpxchgl %k1,%2" + : "=a"(prev) + : "r"(new), "m"(*__synch_xg(ptr)), + "0"(old) + : "memory"); + return prev; + case 8: + __asm__ __volatile__("lock; cmpxchgq %1,%2" + : "=a"(prev) + : "r"(new), "m"(*__synch_xg(ptr)), + "0"(old) + : "memory"); + return prev; +#else + case 4: + __asm__ __volatile__("lock; cmpxchgl %1,%2" + : "=a"(prev) + : "r"(new), "m"(*__synch_xg(ptr)), + "0"(old) + : "memory"); + return prev; +#endif + } + return old; +} static __inline__ void synch_set_bit(int nr, volatile void * addr) diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/include/xenbus.h --- a/extras/mini-os/include/xenbus.h Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/include/xenbus.h Wed Jul 05 20:11:37 2006 -0600 @@ -1,5 +1,8 @@ #ifndef XENBUS_H__ #define XENBUS_H__ + +typedef unsigned long xenbus_transaction_t; +#define XBT_NIL ((xenbus_transaction_t)0) /* Initialize the XenBus system. */ void init_xenbus(void); @@ -7,28 +10,42 @@ void init_xenbus(void); /* Read the value associated with a path. Returns a malloc'd error string on failure and sets *value to NULL. On success, *value is set to a malloc'd copy of the value. */ -char *xenbus_read(const char *path, char **value); +char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value); /* Associates a value with a path. Returns a malloc'd error string on failure. */ -char *xenbus_write(const char *path, const char *value); +char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value); /* Removes the value associated with a path. Returns a malloc'd error string on failure. */ -char *xenbus_rm(const char *path); +char *xenbus_rm(xenbus_transaction_t xbt, const char *path); /* List the contents of a directory. Returns a malloc'd error string on failure and sets *contents to NULL. On success, *contents is set to a malloc'd array of pointers to malloc'd strings. The array is NULL terminated. May block. */ -char *xenbus_ls(const char *prefix, char ***contents); +char *xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char ***contents); /* Reads permissions associated with a path. Returns a malloc'd error string on failure and sets *value to NULL. On success, *value is set to a malloc'd copy of the value. */ -char *xenbus_get_perms(const char *path, char **value); +char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value); /* Sets the permissions associated with a path. Returns a malloc'd error string on failure. */ -char *xenbus_set_perms(const char *path, domid_t dom, char perm); +char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm); + +/* Start a xenbus transaction. Returns the transaction in xbt on + success or a malloc'd error string otherwise. */ +char *xenbus_transaction_start(xenbus_transaction_t *xbt); + +/* End a xenbus transaction. Returns a malloc'd error string if it + fails. abort says whether the transaction should be aborted. + Returns 1 in *retry iff the transaction should be retried. */ +char *xenbus_transaction_end(xenbus_transaction_t, int abort, + int *retry); + +/* Read path and parse it as an integer. Returns -1 on error. */ +int xenbus_read_integer(char *path); + #endif /* XENBUS_H__ */ diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/kernel.c Wed Jul 05 20:11:37 2006 -0600 @@ -35,6 +35,7 @@ #include <lib.h> #include <sched.h> #include <xenbus.h> +#include <gnttab.h> #include <xen/features.h> #include <xen/version.h> @@ -104,7 +105,8 @@ void test_xenbus(void); void xenbus_tester(void *p) { - test_xenbus(); + printk("Xenbus tests disabled, because of a Xend bug.\n"); + /* test_xenbus(); */ } /* This should be overridden by the application we are linked against. */ @@ -176,7 +178,10 @@ void start_kernel(start_info_t *si) /* Init the console driver. */ init_console(); - + + /* Init grant tables */ + init_gnttab(); + /* Init scheduler. */ init_sched(); diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/lib/string.c --- a/extras/mini-os/lib/string.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/lib/string.c Wed Jul 05 20:11:37 2006 -0600 @@ -23,6 +23,7 @@ #include <os.h> #include <types.h> #include <lib.h> +#include <xmalloc.h> int memcmp(const void * cs,const void * ct,size_t count) { @@ -156,4 +157,13 @@ char * strstr(const char * s1,const char return NULL; } +char *strdup(const char *x) +{ + int l = strlen(x); + char *res = malloc(l + 1); + if (!res) return NULL; + memcpy(res, x, l + 1); + return res; +} + #endif diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/mm.c --- a/extras/mini-os/mm.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/mm.c Wed Jul 05 20:11:37 2006 -0600 @@ -343,7 +343,7 @@ void free_pages(void *pointer, int order break; /* Merge with successor */ - freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask); + freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask) - 1; } /* We are commited to merging, unlink the chunk */ @@ -612,6 +612,107 @@ void mem_test(unsigned long *start_add, } +static pgentry_t *demand_map_pgt; +static void *demand_map_area_start; + +static void init_demand_mapping_area(unsigned long max_pfn) +{ + unsigned long mfn; + pgentry_t *tab; + unsigned long start_addr; + unsigned long pt_pfn; + unsigned offset; + + /* Round up to four megs. + 1024 rather than + 1023 since we want + to be sure we don't end up in the same place we started. */ + max_pfn = (max_pfn + L1_PAGETABLE_ENTRIES) & ~(L1_PAGETABLE_ENTRIES - 1); + if (max_pfn == 0 || + (unsigned long)pfn_to_virt(max_pfn + L1_PAGETABLE_ENTRIES) >= + HYPERVISOR_VIRT_START) { + printk("Too much memory; no room for demand map hole.\n"); + do_exit(); + } + + demand_map_area_start = pfn_to_virt(max_pfn); + printk("Demand map pfns start at %lx (%p).\n", max_pfn, + demand_map_area_start); + start_addr = (unsigned long)demand_map_area_start; + + tab = (pgentry_t *)start_info.pt_base; + mfn = virt_to_mfn(start_info.pt_base); + pt_pfn = virt_to_pfn(alloc_page()); + +#if defined(__x86_64__) + offset = l4_table_offset(start_addr); + if (!(tab[offset] & _PAGE_PRESENT)) { + new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME); + pt_pfn = virt_to_pfn(alloc_page()); + } + ASSERT(tab[offset] & _PAGE_PRESENT); + mfn = pte_to_mfn(tab[offset]); + tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT); +#endif +#if defined(__x86_64__) || defined(CONFIG_X86_PAE) + offset = l3_table_offset(start_addr); + if (!(tab[offset] & _PAGE_PRESENT)) { + new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME); + pt_pfn = virt_to_pfn(alloc_page()); + } + ASSERT(tab[offset] & _PAGE_PRESENT); + mfn = pte_to_mfn(tab[offset]); + tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT); +#endif + offset = l2_table_offset(start_addr); + if (tab[offset] & _PAGE_PRESENT) { + printk("Demand map area already has a page table covering it?\n"); + BUG(); + } + demand_map_pgt = pfn_to_virt(pt_pfn); + new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME); + ASSERT(tab[offset] & _PAGE_PRESENT); +} + +void *map_frames(unsigned long *f, unsigned long n) +{ + unsigned long x; + unsigned long y = 0; + mmu_update_t mmu_updates[16]; + int rc; + + if (n > 16) { + printk("Tried to map too many (%ld) frames at once.\n", n); + return NULL; + } + + /* Find a run of n contiguous frames */ + for (x = 0; x <= 1024 - n; x += y + 1) { + for (y = 0; y < n; y++) + if (demand_map_pgt[y] & _PAGE_PRESENT) + break; + if (y == n) + break; + } + if (y != n) { + printk("Failed to map %ld frames!\n", n); + return NULL; + } + + /* Found it at x. Map it in. */ + for (y = 0; y < n; y++) { + mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]); + mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT; + } + + rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF); + if (rc < 0) { + printk("Map %ld failed: %d.\n", n, rc); + return NULL; + } else { + return (void *)(unsigned long)((unsigned long)demand_map_area_start + + x * PAGE_SIZE); + } +} + void init_mm(void) { @@ -643,4 +744,24 @@ void init_mm(void) (u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn)); init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn)); printk("MM: done\n"); -} + + init_demand_mapping_area(max_pfn); + printk("Initialised demand area.\n"); +} + +void sanity_check(void) +{ + int x; + chunk_head_t *head; + + for (x = 0; x < FREELIST_SIZE; x++) { + for (head = free_head[x]; !FREELIST_EMPTY(head); head = head->next) { + ASSERT(!allocated_in_map(virt_to_pfn(head))); + if (head->next) + ASSERT(head->next->pprev == &head->next); + } + if (free_head[x]) { + ASSERT(free_head[x]->pprev == &free_head[x]); + } + } +} diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/time.c --- a/extras/mini-os/time.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/time.c Wed Jul 05 20:11:37 2006 -0600 @@ -215,7 +215,7 @@ void block_domain(u32 millisecs) /* * Just a dummy */ -static void timer_handler(int ev, struct pt_regs *regs) +static void timer_handler(int ev, struct pt_regs *regs, void *ign) { static int i; @@ -233,5 +233,5 @@ void init_time(void) void init_time(void) { printk("Initialising timer interface\n"); - bind_virq(VIRQ_TIMER, &timer_handler); -} + bind_virq(VIRQ_TIMER, &timer_handler, NULL); +} diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Wed Jul 05 10:23:54 2006 -0600 +++ b/extras/mini-os/xenbus/xenbus.c Wed Jul 05 20:11:37 2006 -0600 @@ -112,7 +112,7 @@ static void xenbus_thread_func(void *ign } } -static void xenbus_evtchn_handler(int port, struct pt_regs *regs) +static void xenbus_evtchn_handler(int port, struct pt_regs *regs, void *ign) { wake_up(&xb_waitq); } @@ -174,7 +174,8 @@ void init_xenbus(void) create_thread("xenstore", xenbus_thread_func, NULL); DEBUG("buf at %p.\n", xenstore_buf); err = bind_evtchn(start_info.store_evtchn, - xenbus_evtchn_handler); + xenbus_evtchn_handler, + NULL); DEBUG("xenbus on irq %d\n", err); } @@ -187,8 +188,8 @@ struct write_req { by xenbus as if sent atomically. The header is added automatically, using type %type, req_id %req_id, and trans_id %trans_id. */ -static void xb_write(int type, int req_id, int trans_id, - const struct write_req *req, int nr_reqs) +static void xb_write(int type, int req_id, xenbus_transaction_t trans_id, + const struct write_req *req, int nr_reqs) { XENSTORE_RING_IDX prod; int r; @@ -266,9 +267,9 @@ static void xb_write(int type, int req_i freed by the caller. */ static struct xsd_sockmsg * xenbus_msg_reply(int type, - int trans, - struct write_req *io, - int nr_reqs) + xenbus_transaction_t trans, + struct write_req *io, + int nr_reqs) { int id; DEFINE_WAIT(w); @@ -322,14 +323,14 @@ static void xenbus_debug_msg(const char /* List the contents of a directory. Returns a malloc()ed array of pointers to malloc()ed strings. The array is NULL terminated. May block. */ -char *xenbus_ls(const char *pre, char ***contents) +char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents) { struct xsd_sockmsg *reply, *repmsg; struct write_req req[] = { { pre, strlen(pre)+1 } }; int nr_elems, x, i; char **res; - repmsg = xenbus_msg_reply(XS_DIRECTORY, 0, req, ARRAY_SIZE(req)); + repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(repmsg); if (msg) { *contents = NULL; @@ -351,12 +352,12 @@ char *xenbus_ls(const char *pre, char ** return NULL; } -char *xenbus_read(const char *path, char **value) +char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value) { struct write_req req[] = { {path, strlen(path) + 1} }; struct xsd_sockmsg *rep; char *res; - rep = xenbus_msg_reply(XS_READ, 0, req, ARRAY_SIZE(req)); + rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(rep); if (msg) { *value = NULL; @@ -370,14 +371,14 @@ char *xenbus_read(const char *path, char return NULL; } -char *xenbus_write(const char *path, const char *value) +char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value) { struct write_req req[] = { {path, strlen(path) + 1}, {value, strlen(value) + 1}, }; struct xsd_sockmsg *rep; - rep = xenbus_msg_reply(XS_WRITE, 0, req, ARRAY_SIZE(req)); + rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(rep); if (msg) return msg; @@ -385,11 +386,11 @@ char *xenbus_write(const char *path, con return NULL; } -char *xenbus_rm(const char *path) +char *xenbus_rm(xenbus_transaction_t xbt, const char *path) { struct write_req req[] = { {path, strlen(path) + 1} }; struct xsd_sockmsg *rep; - rep = xenbus_msg_reply(XS_RM, 0, req, ARRAY_SIZE(req)); + rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(rep); if (msg) return msg; @@ -397,12 +398,12 @@ char *xenbus_rm(const char *path) return NULL; } -char *xenbus_get_perms(const char *path, char **value) +char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value) { struct write_req req[] = { {path, strlen(path) + 1} }; struct xsd_sockmsg *rep; char *res; - rep = xenbus_msg_reply(XS_GET_PERMS, 0, req, ARRAY_SIZE(req)); + rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(rep); if (msg) { *value = NULL; @@ -417,7 +418,7 @@ char *xenbus_get_perms(const char *path, } #define PERM_MAX_SIZE 32 -char *xenbus_set_perms(const char *path, domid_t dom, char perm) +char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm) { char value[PERM_MAX_SIZE]; snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom); @@ -426,7 +427,7 @@ char *xenbus_set_perms(const char *path, {value, strlen(value) + 1}, }; struct xsd_sockmsg *rep; - rep = xenbus_msg_reply(XS_SET_PERMS, 0, req, ARRAY_SIZE(req)); + rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req)); char *msg = errmsg(rep); if (msg) return msg; @@ -434,13 +435,72 @@ char *xenbus_set_perms(const char *path, return NULL; } +char *xenbus_transaction_start(xenbus_transaction_t *xbt) +{ + /* xenstored becomes angry if you send a length 0 message, so just + shove a nul terminator on the end */ + struct write_req req = { "", 1}; + struct xsd_sockmsg *rep; + char *err; + + rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1); + err = errmsg(rep); + if (err) + return err; + sscanf((char *)(rep + 1), "%u", xbt); + free(rep); + return NULL; +} + +char * +xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry) +{ + struct xsd_sockmsg *rep; + struct write_req req; + char *err; + + *retry = 0; + + req.data = abort ? "F" : "T"; + req.len = 2; + rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1); + err = errmsg(rep); + if (err) { + if (!strcmp(err, "EAGAIN")) { + *retry = 1; + free(err); + return NULL; + } else { + return err; + } + } + free(rep); + return NULL; +} + +int xenbus_read_integer(char *path) +{ + char *res, *buf; + int t; + + res = xenbus_read(XBT_NIL, path, &buf); + if (res) { + printk("Failed to read %s.\n", path); + free(res); + return -1; + } + sscanf(buf, "%d", &t); + free(buf); + return t; +} + static void do_ls_test(const char *pre) { char **dirs; int x; DEBUG("ls %s...\n", pre); - char *msg = xenbus_ls(pre, &dirs); + char *msg = xenbus_ls(XBT_NIL, pre, &dirs); if (msg) { DEBUG("Error in xenbus ls: %s\n", msg); free(msg); @@ -458,7 +518,7 @@ static void do_read_test(const char *pat { char *res; DEBUG("Read %s...\n", path); - char *msg = xenbus_read(path, &res); + char *msg = xenbus_read(XBT_NIL, path, &res); if (msg) { DEBUG("Error in xenbus read: %s\n", msg); free(msg); @@ -471,7 +531,7 @@ static void do_write_test(const char *pa static void do_write_test(const char *path, const char *val) { DEBUG("Write %s to %s...\n", val, path); - char *msg = xenbus_write(path, val); + char *msg = xenbus_write(XBT_NIL, path, val); if (msg) { DEBUG("Result %s\n", msg); free(msg); @@ -483,7 +543,7 @@ static void do_rm_test(const char *path) static void do_rm_test(const char *path) { DEBUG("rm %s...\n", path); - char *msg = xenbus_rm(path); + char *msg = xenbus_rm(XBT_NIL, path); if (msg) { DEBUG("Result %s\n", msg); free(msg); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/smp-xen.c Wed Jul 05 20:11:37 2006 -0600 @@ -442,6 +442,7 @@ void flush_tlb_mm(struct mm_struct * mm) { xen_tlb_flush_mask(&mm->cpu_vm_mask); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long va) { xen_invlpg_mask(&vma->vm_mm->cpu_vm_mask, va); } +EXPORT_SYMBOL(flush_tlb_page); void flush_tlb_all(void) { xen_tlb_flush_all(); } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Wed Jul 05 20:11:37 2006 -0600 @@ -989,12 +989,11 @@ static void stop_hz_timer(void) smp_mb(); - /* Leave ourselves in 'tick mode' if rcu or softirq pending. */ - if (rcu_needs_cpu(cpu) || local_softirq_pending()) { + /* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */ + if (rcu_needs_cpu(cpu) || local_softirq_pending() || + (j = next_timer_interrupt(), time_before_eq(j, jiffies))) { cpu_clear(cpu, nohz_cpu_mask); j = jiffies + 1; - } else { - j = next_timer_interrupt(); } BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c Wed Jul 05 20:11:37 2006 -0600 @@ -60,7 +60,7 @@ void *kmap_atomic_pte(struct page *page, void kunmap_atomic(void *kvaddr, enum km_type type) { -#ifdef CONFIG_DEBUG_HIGHMEM +#if defined(CONFIG_DEBUG_HIGHMEM) || defined(CONFIG_XEN) unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); @@ -69,7 +69,9 @@ void kunmap_atomic(void *kvaddr, enum km preempt_check_resched(); return; } +#endif +#if defined(CONFIG_DEBUG_HIGHMEM) if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) BUG(); @@ -79,6 +81,14 @@ void kunmap_atomic(void *kvaddr, enum km */ pte_clear(&init_mm, vaddr, kmap_pte-idx); __flush_tlb_one(vaddr); +#elif defined(CONFIG_XEN) + /* + * We must ensure there are no dangling pagetable references when + * returning memory to Xen (decrease_reservation). + * XXX TODO: We could make this faster by only zapping when + * kmap_flush_unused is called but that is trickier and more invasive. + */ + pte_clear(&init_mm, vaddr, kmap_pte-idx); #endif dec_preempt_count(); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Wed Jul 05 20:11:37 2006 -0600 @@ -271,10 +271,6 @@ int xen_create_contiguous_region( int xen_create_contiguous_region( unsigned long vstart, unsigned int order, unsigned int address_bits) { - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; unsigned long *in_frames = discontig_frames, out_frame; unsigned long frame, i, flags; long rc; @@ -301,7 +297,7 @@ int xen_create_contiguous_region( if (xen_feature(XENFEAT_auto_translated_physmap)) return 0; - if (order > MAX_CONTIG_ORDER) + if (unlikely(order > MAX_CONTIG_ORDER)) return -ENOMEM; set_xen_guest_handle(exchange.in.extent_start, in_frames); @@ -313,11 +309,7 @@ int xen_create_contiguous_region( /* 1. Zap current PTEs, remembering MFNs. */ for (i = 0; i < (1UL<<order); i++) { - pgd = pgd_offset_k(vstart + (i*PAGE_SIZE)); - pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE))); - pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE))); - pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE))); - in_frames[i] = pte_mfn(*pte); + in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i); if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), __pte_ma(0), 0)) BUG(); @@ -372,10 +364,6 @@ int xen_create_contiguous_region( void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) { - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; unsigned long *out_frames = discontig_frames, in_frame; unsigned long frame, i, flags; long rc; @@ -397,7 +385,7 @@ void xen_destroy_contiguous_region(unsig !test_bit(__pa(vstart) >> PAGE_SHIFT, contiguous_bitmap)) return; - if (order > MAX_CONTIG_ORDER) + if (unlikely(order > MAX_CONTIG_ORDER)) return; set_xen_guest_handle(exchange.in.extent_start, &in_frame); @@ -410,16 +398,13 @@ void xen_destroy_contiguous_region(unsig contiguous_bitmap_clear(__pa(vstart) >> PAGE_SHIFT, 1UL << order); /* 1. Find start MFN of contiguous extent. */ - pgd = pgd_offset_k(vstart); - pud = pud_offset(pgd, vstart); - pmd = pmd_offset(pud, vstart); - pte = pte_offset_kernel(pmd, vstart); - in_frame = pte_mfn(*pte); + in_frame = pfn_to_mfn(__pa(vstart) >> PAGE_SHIFT); /* 2. Zap current PTEs. */ for (i = 0; i < (1UL<<order); i++) { if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE), - __pte_ma(0), 0)); + __pte_ma(0), 0)) + BUG(); set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, INVALID_P2M_ENTRY); out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i; @@ -430,7 +415,7 @@ void xen_destroy_contiguous_region(unsig success = (exchange.nr_exchanged == 1); BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0))); BUG_ON(success && (rc != 0)); - if (rc == -ENOSYS) { + if (unlikely(rc == -ENOSYS)) { /* Compatibility when XENMEM_exchange is unsupported. */ if (HYPERVISOR_memory_op(XENMEM_decrease_reservation, &exchange.in) != 1) diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/Kconfig --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig Wed Jul 05 20:11:37 2006 -0600 @@ -20,9 +20,18 @@ config TCG_TPM Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI and CONFIG_PNPACPI. +config TCG_TIS + tristate "TPM Interface Specification 1.2 Interface" + depends on TCG_TPM + ---help--- + If you have a TPM security chip that is compliant with the + TCG TIS 1.2 TPM specification say Yes and it will be accessible + from within Linux. To compile this driver as a module, choose + M here; the module will be called tpm_tis. + config TCG_NSC tristate "National Semiconductor TPM Interface" - depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST + depends on TCG_TPM && PNPACPI ---help--- If you have a TPM security chip from National Semicondutor say Yes and it will be accessible from within Linux. To @@ -31,7 +40,7 @@ config TCG_NSC config TCG_ATMEL tristate "Atmel TPM Interface" - depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST + depends on TCG_TPM ---help--- If you have a TPM security chip from Atmel say Yes and it will be accessible from within Linux. To compile this driver diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/Makefile --- a/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Makefile Wed Jul 05 20:11:37 2006 -0600 @@ -5,6 +5,7 @@ ifdef CONFIG_ACPI ifdef CONFIG_ACPI obj-$(CONFIG_TCG_TPM) += tpm_bios.o endif +obj-$(CONFIG_TCG_TIS) += tpm_tis.o obj-$(CONFIG_TCG_NSC) += tpm_nsc.o obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/tpm.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.c Wed Jul 05 20:11:37 2006 -0600 @@ -30,15 +30,295 @@ enum tpm_const { TPM_MINOR = 224, /* officially assigned */ - TPM_MIN_BUFSIZE = 2048, - TPM_MAX_BUFSIZE = 64 * 1024, +#ifndef CONFIG_XEN + TPM_BUFSIZE = 2048, +#endif TPM_NUM_DEVICES = 256, - TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int)) }; + +enum tpm_duration { + TPM_SHORT = 0, + TPM_MEDIUM = 1, + TPM_LONG = 2, + TPM_UNDEFINED, +}; + +#define TPM_MAX_ORDINAL 243 +#define TPM_MAX_PROTECTED_ORDINAL 12 +#define TPM_PROTECTED_ORDINAL_MASK 0xFF static LIST_HEAD(tpm_chip_list); static DEFINE_SPINLOCK(driver_lock); -static int dev_mask[TPM_NUM_MASK_ENTRIES]; +static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); + +/* + * Array with one entry per ordinal defining the maximum amount + * of time the chip could take to return the result. The ordinal + * designation of short, medium or long is defined in a table in + * TCG Specification TPM Main Part 2 TPM Structures Section 17. The + * values of the SHORT, MEDIUM, and LONG durations are retrieved + * from the chip during initialization with a call to tpm_get_timeouts. + */ +static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = { + TPM_UNDEFINED, /* 0 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 5 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 10 */ + TPM_SHORT, +}; + +static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = { + TPM_UNDEFINED, /* 0 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 5 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 10 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_LONG, + TPM_LONG, + TPM_MEDIUM, /* 15 */ + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, + TPM_LONG, + TPM_SHORT, /* 20 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, /* 25 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 30 */ + TPM_LONG, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 35 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 40 */ + TPM_LONG, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 45 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_LONG, + TPM_MEDIUM, /* 50 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 55 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 60 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 65 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 70 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 75 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 80 */ + TPM_UNDEFINED, + TPM_MEDIUM, + TPM_LONG, + TPM_SHORT, + TPM_UNDEFINED, /* 85 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 90 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 95 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 100 */ + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 105 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 110 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 115 */ + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 120 */ + TPM_LONG, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 125 */ + TPM_SHORT, + TPM_LONG, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, /* 130 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_SHORT, + TPM_MEDIUM, + TPM_UNDEFINED, /* 135 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 140 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 145 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 150 */ + TPM_MEDIUM, + TPM_MEDIUM, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 155 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 160 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 165 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_LONG, /* 170 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 175 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_MEDIUM, /* 180 */ + TPM_SHORT, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, /* 185 */ + TPM_SHORT, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 190 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 195 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 200 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 205 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_MEDIUM, /* 210 */ + TPM_UNDEFINED, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_MEDIUM, + TPM_UNDEFINED, /* 215 */ + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, + TPM_SHORT, /* 220 */ + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_SHORT, + TPM_UNDEFINED, /* 225 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 230 */ + TPM_LONG, + TPM_MEDIUM, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, /* 235 */ + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_UNDEFINED, + TPM_SHORT, /* 240 */ + TPM_UNDEFINED, + TPM_MEDIUM, +}; static void user_reader_timeout(unsigned long ptr) { @@ -47,28 +327,58 @@ static void user_reader_timeout(unsigned schedule_work(&chip->work); } -static void timeout_work(void * ptr) +static void timeout_work(void *ptr) { struct tpm_chip *chip = ptr; down(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); +#ifndef CONFIG_XEN + memset(chip->data_buffer, 0, TPM_BUFSIZE); +#else memset(chip->data_buffer, 0, get_chip_buffersize(chip)); +#endif up(&chip->buffer_mutex); } + +/* + * Returns max number of jiffies to wait + */ +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, + u32 ordinal) +{ + int duration_idx = TPM_UNDEFINED; + int duration = 0; + + if (ordinal < TPM_MAX_ORDINAL) + duration_idx = tpm_ordinal_duration[ordinal]; + else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) < + TPM_MAX_PROTECTED_ORDINAL) + duration_idx = + tpm_protected_ordinal_duration[ordinal & + TPM_PROTECTED_ORDINAL_MASK]; + + if (duration_idx != TPM_UNDEFINED) + duration = chip->vendor.duration[duration_idx]; + if (duration <= 0) + return 2 * 60 * HZ; + else + return duration; +} +EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); /* * Internal kernel interface to transmit TPM commands */ -static ssize_t tpm_transmit(struct tpm_chip * chip, const char *buf, +static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, size_t bufsiz) { ssize_t rc; - u32 count; + u32 count, ordinal; unsigned long stop; count = be32_to_cpu(*((__be32 *) (buf + 2))); - + ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); if (count == 0) return -ENODATA; if (count > bufsiz) { @@ -79,21 +389,23 @@ static ssize_t tpm_transmit(struct tpm_c down(&chip->tpm_mutex); - if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { + if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { dev_err(chip->dev, "tpm_transmit: tpm_send: error %zd\n", rc); goto out; } - stop = jiffies + 2 * 60 * HZ; + if (chip->vendor.irq) + goto out_recv; + + stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal); do { - u8 status = chip->vendor->status(chip); - if ((status & chip->vendor->req_complete_mask) == - chip->vendor->req_complete_val) { + u8 status = chip->vendor.status(chip); + if ((status & chip->vendor.req_complete_mask) == + chip->vendor.req_complete_val) goto out_recv; - } - - if ((status == chip->vendor->req_canceled)) { + + if ((status == chip->vendor.req_canceled)) { dev_err(chip->dev, "Operation Canceled\n"); rc = -ECANCELED; goto out; @@ -103,14 +415,13 @@ static ssize_t tpm_transmit(struct tpm_c rmb(); } while (time_before(jiffies, stop)); - - chip->vendor->cancel(chip); + chip->vendor.cancel(chip); dev_err(chip->dev, "Operation Timed out\n"); rc = -ETIME; goto out; out_recv: - rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz); + rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz); if (rc < 0) dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); @@ -120,17 +431,247 @@ out: } #define TPM_DIGEST_SIZE 20 -#define CAP_PCR_RESULT_SIZE 18 -static const u8 cap_pcr[] = { +#define TPM_ERROR_SIZE 10 +#define TPM_RET_CODE_IDX 6 +#define TPM_GET_CAP_RET_SIZE_IDX 10 +#define TPM_GET_CAP_RET_UINT32_1_IDX 14 +#define TPM_GET_CAP_RET_UINT32_2_IDX 18 +#define TPM_GET_CAP_RET_UINT32_3_IDX 22 +#define TPM_GET_CAP_RET_UINT32_4_IDX 26 +#define TPM_GET_CAP_PERM_DISABLE_IDX 16 +#define TPM_GET_CAP_PERM_INACTIVE_IDX 18 +#define TPM_GET_CAP_RET_BOOL_1_IDX 14 +#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 + +#define TPM_CAP_IDX 13 +#define TPM_CAP_SUBCAP_IDX 21 + +enum tpm_capabilities { + TPM_CAP_FLAG = 4, + TPM_CAP_PROP = 5, +}; + +enum tpm_sub_capabilities { + TPM_CAP_PROP_PCR = 0x1, + TPM_CAP_PROP_MANUFACTURER = 0x3, + TPM_CAP_FLAG_PERM = 0x8, + TPM_CAP_FLAG_VOL = 0x9, + TPM_CAP_PROP_OWNER = 0x11, + TPM_CAP_PROP_TIS_TIMEOUT = 0x15, + TPM_CAP_PROP_TIS_DURATION = 0x20, +}; + +/* + * This is a semi generic GetCapability command for use + * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG + * and their associated sub_capabilities. + */ + +static const u8 tpm_cap[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 22, /* length */ 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 5, - 0, 0, 0, 4, - 0, 0, 1, 1 + 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ + 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ + 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ }; -#define READ_PCR_RESULT_SIZE 30 +static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, + char *desc) +{ + int err; + + len = tpm_transmit(chip, data, len); + if (len < 0) + return len; + if (len == TPM_ERROR_SIZE) { + err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); + dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); + return err; + } + return 0; +} + +void tpm_gen_interrupt(struct tpm_chip *chip) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + ssize_t rc; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the timeouts"); +} +EXPORT_SYMBOL_GPL(tpm_gen_interrupt); + +void tpm_get_timeouts(struct tpm_chip *chip) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + ssize_t rc; + u32 timeout; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the timeouts"); + if (rc) + goto duration; + + if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + != 4 * sizeof(u32)) + goto duration; + + /* Don't overwrite default if value is 0 */ + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); + if (timeout) + chip->vendor.timeout_a = msecs_to_jiffies(timeout); + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); + if (timeout) + chip->vendor.timeout_b = msecs_to_jiffies(timeout); + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); + if (timeout) + chip->vendor.timeout_c = msecs_to_jiffies(timeout); + timeout = + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); + if (timeout) + chip->vendor.timeout_d = msecs_to_jiffies(timeout); + +duration: + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the durations"); + if (rc) + return; + + if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + != 3 * sizeof(u32)) + return; + + chip->vendor.duration[TPM_SHORT] = + msecs_to_jiffies(be32_to_cpu + (*((__be32 *) (data + + TPM_GET_CAP_RET_UINT32_1_IDX)))); + chip->vendor.duration[TPM_MEDIUM] = + msecs_to_jiffies(be32_to_cpu + (*((__be32 *) (data + + TPM_GET_CAP_RET_UINT32_2_IDX)))); + chip->vendor.duration[TPM_LONG] = + msecs_to_jiffies(be32_to_cpu + (*((__be32 *) (data + + TPM_GET_CAP_RET_UINT32_3_IDX)))); +} +EXPORT_SYMBOL_GPL(tpm_get_timeouts); + +void tpm_continue_selftest(struct tpm_chip *chip) +{ + u8 data[] = { + 0, 193, /* TPM_TAG_RQU_COMMAND */ + 0, 0, 0, 10, /* length */ + 0, 0, 0, 83, /* TPM_ORD_GetCapability */ + }; + + tpm_transmit(chip, data, sizeof(data)); +} +EXPORT_SYMBOL_GPL(tpm_continue_selftest); + +ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, + char *buf) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_FLAG; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; + + rc = transmit_cmd(chip, data, sizeof(data), + "attemtping to determine the permanent state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_enabled); + +ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, + char *buf) +{ + u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_FLAG; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; + + rc = transmit_cmd(chip, data, sizeof(data), + "attemtping to determine the permanent state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_active); + +ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, + char *buf) +{ + u8 data[sizeof(tpm_cap)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the owner state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_owned); + +ssize_t tpm_show_temp_deactivated(struct device * dev, + struct device_attribute * attr, char *buf) +{ + u8 data[sizeof(tpm_cap)]; + ssize_t rc; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_FLAG; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the temporary state"); + if (rc) + return 0; + return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); +} +EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); + static const u8 pcrread[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 14, /* length */ @@ -141,8 +682,8 @@ ssize_t tpm_show_pcrs(struct device *dev ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[READ_PCR_RESULT_SIZE]; - ssize_t len; + u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; + ssize_t rc; int i, j, num_pcrs; __be32 index; char *str = buf; @@ -151,29 +692,24 @@ ssize_t tpm_show_pcrs(struct device *dev if (chip == NULL) return -ENODEV; - memcpy(data, cap_pcr, sizeof(cap_pcr)); - if ((len = tpm_transmit(chip, data, sizeof(data))) - < CAP_PCR_RESULT_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the number of PCRS\n", - be32_to_cpu(*((__be32 *) (data + 6)))); + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the number of PCRS"); + if (rc) return 0; - } num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); - for (i = 0; i < num_pcrs; i++) { memcpy(data, pcrread, sizeof(pcrread)); index = cpu_to_be32(i); memcpy(data + 10, &index, 4); - if ((len = tpm_transmit(chip, data, sizeof(data))) - < READ_PCR_RESULT_SIZE){ - dev_dbg(chip->dev, "A TPM error (%d) occurred" - " attempting to read PCR %d of %d\n", - be32_to_cpu(*((__be32 *) (data + 6))), - i, num_pcrs); + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to read a PCR"); + if (rc) goto out; - } str += sprintf(str, "PCR-%02d: ", i); for (j = 0; j < TPM_DIGEST_SIZE; j++) str += sprintf(str, "%02X ", *(data + 10 + j)); @@ -195,7 +731,7 @@ ssize_t tpm_show_pubek(struct device *de char *buf) { u8 *data; - ssize_t len; + ssize_t err; int i, rc; char *str = buf; @@ -209,14 +745,10 @@ ssize_t tpm_show_pubek(struct device *de memcpy(data, readpubek, sizeof(readpubek)); - if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) < - READ_PUBEK_RESULT_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to read the PUBEK\n", - be32_to_cpu(*((__be32 *) (data + 6)))); - rc = 0; + err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, + "attempting to read the PUBEK"); + if (err) goto out; - } /* ignore header 10 bytes @@ -246,66 +778,109 @@ ssize_t tpm_show_pubek(struct device *de if ((i + 1) % 16 == 0) str += sprintf(str, "\n"); } +out: rc = str - buf; -out: kfree(data); return rc; } EXPORT_SYMBOL_GPL(tpm_show_pubek); -#define CAP_VER_RESULT_SIZE 18 +#define CAP_VERSION_1_1 6 +#define CAP_VERSION_1_2 0x1A +#define CAP_VERSION_IDX 13 static const u8 cap_version[] = { 0, 193, /* TPM_TAG_RQU_COMMAND */ 0, 0, 0, 18, /* length */ 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0 }; -#define CAP_MANUFACTURER_RESULT_SIZE 18 -static const u8 cap_manufacturer[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 22, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 5, - 0, 0, 0, 4, - 0, 0, 1, 3 -}; - ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[sizeof(cap_manufacturer)]; - ssize_t len; + u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + ssize_t rc; char *str = buf; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; - memcpy(data, cap_manufacturer, sizeof(cap_manufacturer)); - - if ((len = tpm_transmit(chip, data, sizeof(data))) < - CAP_MANUFACTURER_RESULT_SIZE) - return len; + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; + + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the manufacturer"); + if (rc) + return 0; str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + 14)))); + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); memcpy(data, cap_version, sizeof(cap_version)); - - if ((len = tpm_transmit(chip, data, sizeof(data))) < - CAP_VER_RESULT_SIZE) - return len; - - str += - sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[14], (int) data[15], (int) data[16], - (int) data[17]); - + data[CAP_VERSION_IDX] = CAP_VERSION_1_1; + rc = transmit_cmd(chip, data, sizeof(data), + "attempting to determine the 1.1 version"); + if (rc) + goto out; + + str += sprintf(str, + "TCG version: %d.%d\nFirmware version: %d.%d\n", + (int) data[14], (int) data[15], (int) data[16], + (int) data[17]); + +out: return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps); + +ssize_t tpm_show_caps_1_2(struct device * dev, + struct device_attribute * attr, char *buf) +{ + u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + ssize_t len; + char *str = buf; + + struct tpm_chip *chip = dev_get_drvdata(dev); + if (chip == NULL) + return -ENODEV; + + memcpy(data, tpm_cap, sizeof(tpm_cap)); + data[TPM_CAP_IDX] = TPM_CAP_PROP; + data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; + + if ((len = tpm_transmit(chip, data, sizeof(data))) <= + TPM_ERROR_SIZE) { + dev_dbg(chip->dev, "A TPM error (%d) occurred " + "attempting to determine the manufacturer\n", + be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); + return 0; + } + + str += sprintf(str, "Manufacturer: 0x%x\n", + be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); + + memcpy(data, cap_version, sizeof(cap_version)); + data[CAP_VERSION_IDX] = CAP_VERSION_1_2; + + if ((len = tpm_transmit(chip, data, sizeof(data))) <= + TPM_ERROR_SIZE) { + dev_err(chip->dev, "A TPM error (%d) occurred " + "attempting to determine the 1.2 version\n", + be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); + goto out; + } + str += sprintf(str, + "TCG version: %d.%d\nFirmware version: %d.%d\n", + (int) data[16], (int) data[17], (int) data[18], + (int) data[19]); + +out: + return str - buf; +} +EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -314,7 +889,7 @@ ssize_t tpm_store_cancel(struct device * if (chip == NULL) return 0; - chip->vendor->cancel(chip); + chip->vendor.cancel(chip); return count; } EXPORT_SYMBOL_GPL(tpm_store_cancel); @@ -330,7 +905,7 @@ int tpm_open(struct inode *inode, struct spin_lock(&driver_lock); list_for_each_entry(pos, &tpm_chip_list, list) { - if (pos->vendor->miscdev.minor == minor) { + if (pos->vendor.miscdev.minor == minor) { chip = pos; break; } @@ -352,7 +927,12 @@ int tpm_open(struct inode *inode, struct spin_unlock(&driver_lock); - chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8), GFP_KERNEL); +#ifndef CONFIG_XEN + chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL); +#else + chip->data_buffer = kmalloc(get_chip_buffersize(chip) * sizeof(u8), + GFP_KERNEL); +#endif if (chip->data_buffer == NULL) { chip->num_opens--; put_device(chip->dev); @@ -388,7 +968,7 @@ EXPORT_SYMBOL_GPL(tpm_release); EXPORT_SYMBOL_GPL(tpm_release); ssize_t tpm_write(struct file *file, const char __user *buf, - size_t size, loff_t * off) + size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; int in_size = size, out_size; @@ -400,8 +980,13 @@ ssize_t tpm_write(struct file *file, con down(&chip->buffer_mutex); +#ifndef CONFIG_XEN + if (in_size > TPM_BUFSIZE) + in_size = TPM_BUFSIZE; +#else if (in_size > get_chip_buffersize(chip)) in_size = get_chip_buffersize(chip); +#endif if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -410,11 +995,17 @@ ssize_t tpm_write(struct file *file, con } /* atomic tpm command send and result receive */ - out_size = tpm_transmit(chip, chip->data_buffer, +#ifndef CONFIG_XEN + out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); +#else + out_size = tpm_transmit(chip, chip->data_buffer, get_chip_buffersize(chip)); +#endif atomic_set(&chip->data_pending, out_size); +#ifdef CONFIG_XEN atomic_set(&chip->data_position, 0); +#endif up(&chip->buffer_mutex); /* Set a timeout by which the reader must come claim the result */ @@ -422,42 +1013,59 @@ ssize_t tpm_write(struct file *file, con return in_size; } - EXPORT_SYMBOL_GPL(tpm_write); -ssize_t tpm_read(struct file * file, char __user *buf, - size_t size, loff_t * off) +ssize_t tpm_read(struct file *file, char __user *buf, + size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; int ret_size; +#ifdef CONFIG_XEN int pos, pending = 0; - +#endif + +#ifndef CONFIG_XEN + del_singleshot_timer_sync(&chip->user_read_timer); + flush_scheduled_work(); +#endif ret_size = atomic_read(&chip->data_pending); +#ifndef CONFIG_XEN + atomic_set(&chip->data_pending, 0); +#endif if (ret_size > 0) { /* relay data */ if (size < ret_size) ret_size = size; +#ifdef CONFIG_XEN pos = atomic_read(&chip->data_position); - +#endif down(&chip->buffer_mutex); +#ifndef CONFIG_XEN + if (copy_to_user(buf, chip->data_buffer, ret_size)) +#else if (copy_to_user(buf, &chip->data_buffer[pos], ret_size)) { +#endif ret_size = -EFAULT; +#ifdef CONFIG_XEN } else { pending = atomic_read(&chip->data_pending) - ret_size; if ( pending ) { - atomic_set( &chip->data_pending, pending ); - atomic_set( &chip->data_position, pos+ret_size ); + atomic_set(&chip->data_pending, pending); + atomic_set(&chip->data_position, + pos+ret_size); } } +#endif up(&chip->buffer_mutex); } - - if ( ret_size <= 0 || pending == 0 ) { - atomic_set( &chip->data_pending, 0 ); + +#ifdef CONFIG_XEN + if ( ret_size <= 0 || pending == 0 ) { + atomic_set(&chip->data_pending, 0); del_singleshot_timer_sync(&chip->user_read_timer); flush_scheduled_work(); } - +#endif return ret_size; } EXPORT_SYMBOL_GPL(tpm_read); @@ -478,14 +1086,13 @@ void tpm_remove_hardware(struct device * spin_unlock(&driver_lock); dev_set_drvdata(dev, NULL); - misc_deregister(&chip->vendor->miscdev); - kfree(chip->vendor->miscdev.name); - - sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); + misc_deregister(&chip->vendor.miscdev); + kfree(chip->vendor.miscdev.name); + + sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); tpm_bios_log_teardown(chip->bios_dir); - dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= - ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); + clear_bit(chip->dev_num, dev_mask); kfree(chip); @@ -536,18 +1143,18 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume); * upon errant exit from this function specific probe function should call * pci_disable_device */ -int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry) +struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific + *entry) { #define DEVNAME_SIZE 7 char *devname; struct tpm_chip *chip; - int i, j; /* Driver specific per-device data */ chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) - return -ENOMEM; + return NULL; init_MUTEX(&chip->buffer_mutex); init_MUTEX(&chip->tpm_mutex); @@ -559,51 +1166,37 @@ int tpm_register_hardware(struct device chip->user_read_timer.function = user_reader_timeout; chip->user_read_timer.data = (unsigned long) chip; - chip->vendor = entry; - - if (entry->buffersize < TPM_MIN_BUFSIZE) { - entry->buffersize = TPM_MIN_BUFSIZE; - } else if (entry->buffersize > TPM_MAX_BUFSIZE) { - entry->buffersize = TPM_MAX_BUFSIZE; - } - - chip->dev_num = -1; - - for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++) - for (j = 0; j < 8 * sizeof(int); j++) - if ((dev_mask[i] & (1 << j)) == 0) { - chip->dev_num = - i * TPM_NUM_MASK_ENTRIES + j; - dev_mask[i] |= 1 << j; - goto dev_num_search_complete; - } - -dev_num_search_complete: - if (chip->dev_num < 0) { + memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific)); + + chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); + + if (chip->dev_num >= TPM_NUM_DEVICES) { dev_err(dev, "No available tpm device numbers\n"); kfree(chip); - return -ENODEV; + return NULL; } else if (chip->dev_num == 0) - chip->vendor->miscdev.minor = TPM_MINOR; + chip->vendor.miscdev.minor = TPM_MINOR; else - chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR; + chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; + + set_bit(chip->dev_num, dev_mask); devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); - chip->vendor->miscdev.name = devname; - - chip->vendor->miscdev.dev = dev; + chip->vendor.miscdev.name = devname; + + chip->vendor.miscdev.dev = dev; chip->dev = get_device(dev); - if (misc_register(&chip->vendor->miscdev)) { + if (misc_register(&chip->vendor.miscdev)) { dev_err(chip->dev, "unable to misc_register %s, minor %d\n", - chip->vendor->miscdev.name, - chip->vendor->miscdev.minor); + chip->vendor.miscdev.name, + chip->vendor.miscdev.minor); put_device(dev); + clear_bit(chip->dev_num, dev_mask); kfree(chip); - dev_mask[i] &= !(1 << j); - return -ENODEV; + return NULL; } spin_lock(&driver_lock); @@ -614,11 +1207,11 @@ dev_num_search_complete: spin_unlock(&driver_lock); - sysfs_create_group(&dev->kobj, chip->vendor->attr_group); + sysfs_create_group(&dev->kobj, chip->vendor.attr_group); chip->bios_dir = tpm_bios_log_setup(devname); - return 0; + return chip; } EXPORT_SYMBOL_GPL(tpm_register_hardware); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/tpm.h --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm.h Wed Jul 05 20:11:37 2006 -0600 @@ -24,6 +24,14 @@ #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/platform_device.h> +#include <linux/io.h> + +#ifdef CONFIG_XEN +enum tpm_bufsize { + TPM_MIN_BUFFERSIZE = 2048, + TPM_MAX_BUFFERSIZE = 64 * 1024, +}; +#endif enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -41,18 +49,32 @@ extern ssize_t tpm_show_pcrs(struct devi char *); extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, char *); +extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr, + char *); extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, const char *, size_t); +extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr, + char *); +extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr, + char *); +extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, + char *); +extern ssize_t tpm_show_temp_deactivated(struct device *, + struct device_attribute *attr, char *); struct tpm_chip; struct tpm_vendor_specific { - u8 req_complete_mask; - u8 req_complete_val; - u8 req_canceled; + const u8 req_complete_mask; + const u8 req_complete_val; + const u8 req_canceled; +#ifdef CONFIG_XEN u32 buffersize; +#endif void __iomem *iobase; /* ioremapped address */ unsigned long base; /* TPM base address */ + + int irq; int region_size; int have_region; @@ -63,6 +85,13 @@ struct tpm_vendor_specific { u8 (*status) (struct tpm_chip *); struct miscdevice miscdev; struct attribute_group *attr_group; + struct list_head list; + int locality; + unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ + unsigned long duration[3]; /* jiffies */ + + wait_queue_head_t read_queue; + wait_queue_head_t int_queue; }; struct tpm_chip { @@ -75,19 +104,26 @@ struct tpm_chip { /* Data passed to and from the tpm via the read/write calls */ u8 *data_buffer; atomic_t data_pending; +#ifdef CONFIG_XEN atomic_t data_position; +#endif struct semaphore buffer_mutex; struct timer_list user_read_timer; /* user needs to claim result */ struct work_struct work; struct semaphore tpm_mutex; /* tpm is processing */ - struct tpm_vendor_specific *vendor; + struct tpm_vendor_specific vendor; struct dentry **bios_dir; struct list_head list; +#ifdef CONFIG_XEN + void *priv; +#endif }; + +#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) static inline int tpm_read_index(int base, int index) { @@ -101,13 +137,35 @@ static inline void tpm_write_index(int b outb(value & 0xFF, base+1); } +#ifdef CONFIG_XEN static inline u32 get_chip_buffersize(struct tpm_chip *chip) { - return chip->vendor->buffersize; + u32 size = chip->vendor.buffersize; + if (size > TPM_MAX_BUFFERSIZE) { + return TPM_MAX_BUFFERSIZE; + } else if (size < TPM_MIN_BUFFERSIZE) { + return TPM_MIN_BUFFERSIZE; + } + return size; } -extern int tpm_register_hardware(struct device *, - struct tpm_vendor_specific *); +static inline void *chip_get_private(const struct tpm_chip *chip) +{ + return chip->priv; +} + +static inline void chip_set_private(struct tpm_chip *chip, void *priv) +{ + chip->priv = priv; +} +#endif + +extern void tpm_get_timeouts(struct tpm_chip *); +extern void tpm_gen_interrupt(struct tpm_chip *); +extern void tpm_continue_selftest(struct tpm_chip *); +extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); +extern struct tpm_chip* tpm_register_hardware(struct device *, + const struct tpm_vendor_specific *); extern int tpm_open(struct inode *, struct file *); extern int tpm_release(struct inode *, struct file *); extern ssize_t tpm_write(struct file *, const char __user *, size_t, @@ -121,7 +179,7 @@ extern struct dentry ** tpm_bios_log_set extern struct dentry ** tpm_bios_log_setup(char *); extern void tpm_bios_log_teardown(struct dentry **); #else -static inline struct dentry* tpm_bios_log_setup(char *name) +static inline struct dentry ** tpm_bios_log_setup(char *name) { return NULL; } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Wed Jul 05 20:11:37 2006 -0600 @@ -29,8 +29,6 @@ enum { STATUS_READY = 0x04 }; -#define MIN(x,y) ((x) < (y)) ? (x) : (y) - struct transmission { struct list_head next; @@ -49,26 +47,6 @@ enum { TRANSMISSION_FLAG_WAS_QUEUED = 0x1 }; -struct vtpm_state { - struct transmission *current_request; - spinlock_t req_list_lock; - wait_queue_head_t req_wait_queue; - - struct list_head queued_requests; - - struct transmission *current_response; - spinlock_t resp_list_lock; - wait_queue_head_t resp_wait_queue; // processes waiting for responses - - struct transmission *req_cancelled; // if a cancellation was encounterd - - u8 vd_status; - u8 flags; - - unsigned long disconnect_time; - - struct tpm_virtual_device *tpmvd; -}; enum { DATAEX_FLAG_QUEUED_ONLY = 0x1 @@ -76,7 +54,6 @@ enum { /* local variables */ -static struct vtpm_state *vtpms; /* local function prototypes */ static int _vtpm_send_queued(struct tpm_chip *chip); @@ -160,11 +137,16 @@ static inline void transmission_free(str /* * Lower layer uses this function to make a response available. */ -int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr) +int vtpm_vd_recv(const struct tpm_chip *chip, + const unsigned char *buffer, size_t count, + void *ptr) { unsigned long flags; int ret_size = 0; struct transmission *t; + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); /* * The list with requests must contain one request @@ -173,26 +155,11 @@ int vtpm_vd_recv(const unsigned char *bu */ spin_lock_irqsave(&vtpms->resp_list_lock, flags); if (vtpms->current_request != ptr) { - printk("WARNING: The request pointer is different than the " - "pointer the shared memory driver returned to me. " - "%p != %p\n", - vtpms->current_request, ptr); - } - - /* - * If the request has been cancelled, just quit here - */ - if (vtpms->req_cancelled == (struct transmission *)ptr) { - if (vtpms->current_request == vtpms->req_cancelled) { - vtpms->current_request = NULL; - } - transmission_free(vtpms->req_cancelled); - vtpms->req_cancelled = NULL; spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); return 0; } - if (NULL != (t = vtpms->current_request)) { + if ((t = vtpms->current_request)) { transmission_free(t); vtpms->current_request = NULL; } @@ -217,8 +184,12 @@ int vtpm_vd_recv(const unsigned char *bu /* * Lower layer indicates its status (connected/disconnected) */ -void vtpm_vd_status(u8 vd_status) -{ +void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status) +{ + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); + vtpms->vd_status = vd_status; if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) { vtpms->disconnect_time = jiffies; @@ -233,6 +204,9 @@ static int vtpm_recv(struct tpm_chip *ch { int rc = 0; unsigned long flags; + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); /* * Check if the previous operation only queued the command @@ -251,7 +225,7 @@ static int vtpm_recv(struct tpm_chip *ch * Return a response of up to 30 '0's. */ - count = MIN(count, 30); + count = min_t(size_t, count, 30); memset(buf, 0x0, count); return count; } @@ -270,7 +244,7 @@ static int vtpm_recv(struct tpm_chip *ch if (vtpms->current_response) { struct transmission *t = vtpms->current_response; vtpms->current_response = NULL; - rc = MIN(count, t->response_len); + rc = min(count, t->response_len); memcpy(buf, t->response, rc); transmission_free(t); } @@ -284,6 +258,9 @@ static int vtpm_send(struct tpm_chip *ch int rc = 0; unsigned long flags; struct transmission *t = transmission_alloc(); + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); if (!t) return -ENOMEM; @@ -327,8 +304,7 @@ static int vtpm_send(struct tpm_chip *ch vtpms->current_request = t; - rc = vtpm_vd_send(chip, - vtpms->tpmvd->tpm_private, + rc = vtpm_vd_send(vtpms->tpm_private, buf, count, t); @@ -373,6 +349,8 @@ static int _vtpm_send_queued(struct tpm_ int error = 0; long flags; unsigned char buffer[1]; + struct vtpm_state *vtpms; + vtpms = (struct vtpm_state *)chip_get_private(chip); spin_lock_irqsave(&vtpms->req_list_lock, flags); @@ -387,8 +365,7 @@ static int _vtpm_send_queued(struct tpm_ vtpms->current_request = qt; spin_unlock_irqrestore(&vtpms->req_list_lock, flags); - rc = vtpm_vd_send(chip, - vtpms->tpmvd->tpm_private, + rc = vtpm_vd_send(vtpms->tpm_private, qt->request, qt->request_len, qt); @@ -427,9 +404,21 @@ static void vtpm_cancel(struct tpm_chip static void vtpm_cancel(struct tpm_chip *chip) { unsigned long flags; + struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip); + spin_lock_irqsave(&vtpms->resp_list_lock,flags); - vtpms->req_cancelled = vtpms->current_request; + if (!vtpms->current_response && vtpms->current_request) { + spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); + interruptible_sleep_on(&vtpms->resp_wait_queue); + spin_lock_irqsave(&vtpms->resp_list_lock,flags); + } + + if (vtpms->current_response) { + struct transmission *t = vtpms->current_response; + vtpms->current_response = NULL; + transmission_free(t); + } spin_unlock_irqrestore(&vtpms->resp_list_lock,flags); } @@ -438,6 +427,9 @@ static u8 vtpm_status(struct tpm_chip *c { u8 rc = 0; unsigned long flags; + struct vtpm_state *vtpms; + + vtpms = (struct vtpm_state *)chip_get_private(chip); spin_lock_irqsave(&vtpms->resp_list_lock, flags); /* @@ -449,7 +441,10 @@ static u8 vtpm_status(struct tpm_chip *c if (vtpms->current_response || 0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) { rc = STATUS_DATA_AVAIL; - } + } else if (!vtpms->current_response && !vtpms->current_request) { + rc = STATUS_READY; + } + spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); return rc; } @@ -465,18 +460,29 @@ static struct file_operations vtpm_ops = static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); +static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); +static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); +static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); +static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, + NULL); static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel); static struct attribute *vtpm_attrs[] = { &dev_attr_pubek.attr, &dev_attr_pcrs.attr, + &dev_attr_enabled.attr, + &dev_attr_active.attr, + &dev_attr_owned.attr, + &dev_attr_temp_deactivated.attr, &dev_attr_caps.attr, &dev_attr_cancel.attr, NULL, }; static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs }; + +#define TPM_LONG_TIMEOUT (10 * 60 * HZ) static struct tpm_vendor_specific tpm_vtpm = { .recv = vtpm_recv, @@ -486,61 +492,56 @@ static struct tpm_vendor_specific tpm_vt .req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL, .req_complete_val = STATUS_DATA_AVAIL, .req_canceled = STATUS_READY, - .base = 0, .attr_group = &vtpm_attr_grp, .miscdev = { .fops = &vtpm_ops, }, -}; - -static struct platform_device *pdev; - -int __init init_vtpm(struct tpm_virtual_device *tvd) -{ - int rc; - - /* vtpms is global - only allow one user */ - if (vtpms) - return -EBUSY; + .duration = { + TPM_LONG_TIMEOUT, + TPM_LONG_TIMEOUT, + TPM_LONG_TIMEOUT, + }, +}; + +struct tpm_chip *init_vtpm(struct device *dev, + struct tpm_virtual_device *tvd, + struct tpm_private *tp) +{ + long rc; + struct tpm_chip *chip; + struct vtpm_state *vtpms; vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL); if (!vtpms) - return -ENOMEM; + return ERR_PTR(-ENOMEM); vtpm_state_init(vtpms); vtpms->tpmvd = tvd; - - pdev = platform_device_register_simple("tpm_vtpm", -1, NULL, 0); - if (IS_ERR(pdev)) { - rc = PTR_ERR(pdev); - goto err_free_mem; - } + vtpms->tpm_private = tp; if (tvd) tpm_vtpm.buffersize = tvd->max_tx_size; - if ((rc = tpm_register_hardware(&pdev->dev, &tpm_vtpm)) < 0) { - goto err_unreg_pdev; - } - - return 0; - -err_unreg_pdev: - platform_device_unregister(pdev); + chip = tpm_register_hardware(dev, &tpm_vtpm); + if (!chip) { + rc = -ENODEV; + goto err_free_mem; + } + + chip_set_private(chip, vtpms); + + return chip; + err_free_mem: kfree(vtpms); - vtpms = NULL; - - return rc; -} - -void __exit cleanup_vtpm(void) -{ - struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); - if (chip) { - tpm_remove_hardware(chip->dev); - platform_device_unregister(pdev); - } + + return ERR_PTR(rc); +} + +void cleanup_vtpm(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip); + tpm_remove_hardware(dev); kfree(vtpms); - vtpms = NULL; -} +} diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Wed Jul 05 20:11:37 2006 -0600 @@ -12,6 +12,26 @@ struct tpm_virtual_device { * for allocation of buffers. */ unsigned int max_tx_size; +}; + +struct vtpm_state { + struct transmission *current_request; + spinlock_t req_list_lock; + wait_queue_head_t req_wait_queue; + + struct list_head queued_requests; + + struct transmission *current_response; + spinlock_t resp_list_lock; + wait_queue_head_t resp_wait_queue; // processes waiting for responses + + u8 vd_status; + u8 flags; + + unsigned long disconnect_time; + + struct tpm_virtual_device *tpmvd; + /* * The following is a private structure of the underlying * driver. It is passed as parameter in the send function. @@ -19,20 +39,30 @@ struct tpm_virtual_device { struct tpm_private *tpm_private; }; + enum vdev_status { TPM_VD_STATUS_DISCONNECTED = 0x0, TPM_VD_STATUS_CONNECTED = 0x1 }; /* this function is called from tpm_vtpm.c */ -int vtpm_vd_send(struct tpm_chip *tc, - struct tpm_private * tp, +int vtpm_vd_send(struct tpm_private * tp, const u8 * buf, size_t count, void *ptr); /* these functions are offered by tpm_vtpm.c */ -int __init init_vtpm(struct tpm_virtual_device *); -void __exit cleanup_vtpm(void); -int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr); -void vtpm_vd_status(u8 status); +struct tpm_chip *init_vtpm(struct device *, + struct tpm_virtual_device *, + struct tpm_private *); +void cleanup_vtpm(struct device *); +int vtpm_vd_recv(const struct tpm_chip* chip, + const unsigned char *buffer, size_t count, void *ptr); +void vtpm_vd_status(const struct tpm_chip *, u8 status); + +static inline struct tpm_private *tpm_private_from_dev(struct device *dev) +{ + struct tpm_chip *chip = dev_get_drvdata(dev); + struct vtpm_state *vtpms = chip_get_private(chip); + return vtpms->tpm_private; +} #endif diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Wed Jul 05 20:11:37 2006 -0600 @@ -34,6 +34,7 @@ */ #include <linux/errno.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/mutex.h> #include <asm/uaccess.h> @@ -41,12 +42,15 @@ #include <xen/interface/grant_table.h> #include <xen/interface/io/tpmif.h> #include <xen/xenbus.h> +#include "tpm.h" #include "tpm_vtpm.h" #undef DEBUG /* local structures */ struct tpm_private { + struct tpm_chip *chip; + tpmif_tx_interface_t *tx; atomic_t refcnt; unsigned int evtchn; @@ -60,6 +64,7 @@ struct tpm_private { atomic_t tx_busy; void *tx_remember; + domid_t backend_id; wait_queue_head_t wait_q; @@ -95,6 +100,7 @@ static int tpm_xmit(struct tpm_private * const u8 * buf, size_t count, int userbuffer, void *remember); static void destroy_tpmring(struct tpm_private *tp); +void __exit tpmif_exit(void); #define DPRINTK(fmt, args...) \ pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) @@ -199,8 +205,7 @@ static DEFINE_MUTEX(suspend_lock); /* * Send data via this module by calling this function */ -int vtpm_vd_send(struct tpm_chip *chip, - struct tpm_private *tp, +int vtpm_vd_send(struct tpm_private *tp, const u8 * buf, size_t count, void *ptr) { int sent; @@ -331,7 +336,7 @@ static void backend_changed(struct xenbu static void backend_changed(struct xenbus_device *dev, enum xenbus_state backend_state) { - struct tpm_private *tp = dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); DPRINTK("\n"); switch (backend_state) { @@ -358,6 +363,9 @@ static void backend_changed(struct xenbu } } +struct tpm_virtual_device tvd = { + .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE, +}; static int tpmfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) @@ -368,6 +376,12 @@ static int tpmfront_probe(struct xenbus_ if (!tp) return -ENOMEM; + + tp->chip = init_vtpm(&dev->dev, &tvd, tp); + + if (IS_ERR(tp->chip)) { + return PTR_ERR(tp->chip); + } err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%i", &handle); @@ -380,12 +394,10 @@ static int tpmfront_probe(struct xenbus_ } tp->dev = dev; - dev->dev.driver_data = tp; err = talk_to_backend(dev, tp); if (err) { tpm_private_put(); - dev->dev.driver_data = NULL; return err; } return 0; @@ -394,16 +406,16 @@ static int tpmfront_probe(struct xenbus_ static int tpmfront_remove(struct xenbus_device *dev) { - struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); destroy_tpmring(tp); + cleanup_vtpm(&dev->dev); return 0; } static int tpmfront_suspend(struct xenbus_device *dev) { - struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); u32 ctr; - /* lock, so no app can send */ mutex_lock(&suspend_lock); tp->is_suspended = 1; @@ -431,7 +443,7 @@ static int tpmfront_suspend(struct xenbu static int tpmfront_resume(struct xenbus_device *dev) { - struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data; + struct tpm_private *tp = tpm_private_from_dev(&dev->dev); destroy_tpmring(tp); return talk_to_backend(dev, tp); } @@ -548,7 +560,7 @@ static void tpmif_rx_action(unsigned lon offset += tocopy; } - vtpm_vd_recv(buffer, received, tp->tx_remember); + vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember); kfree(buffer); exit: @@ -638,6 +650,7 @@ static int tpm_xmit(struct tpm_private * atomic_set(&tp->tx_busy, 1); tp->tx_remember = remember; + mb(); DPRINTK("Notifying backend via event channel %d\n", @@ -657,9 +670,9 @@ static void tpmif_notify_upperlayer(stru * to the BE. */ if (tp->is_connected) { - vtpm_vd_status(TPM_VD_STATUS_CONNECTED); + vtpm_vd_status(tp->chip, TPM_VD_STATUS_CONNECTED); } else { - vtpm_vd_status(TPM_VD_STATUS_DISCONNECTED); + vtpm_vd_status(tp->chip, TPM_VD_STATUS_DISCONNECTED); } } @@ -699,13 +712,10 @@ static void tpmif_set_connected_state(st * ================================================================= */ -struct tpm_virtual_device tvd = { - .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE, -}; static int __init tpmif_init(void) { - int rc; + long rc = 0; struct tpm_private *tp; if ((xen_start_info->flags & SIF_INITDOMAIN)) { @@ -717,11 +727,6 @@ static int __init tpmif_init(void) rc = -ENOMEM; goto failexit; } - - tvd.tpm_private = tp; - rc = init_vtpm(&tvd); - if (rc) - goto init_vtpm_failed; IPRINTK("Initialising the vTPM driver.\n"); if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE, @@ -734,19 +739,16 @@ static int __init tpmif_init(void) return 0; gnttab_alloc_failed: - cleanup_vtpm(); -init_vtpm_failed: tpm_private_put(); failexit: - return rc; -} - - -static void __exit tpmif_exit(void) + return (int)rc; +} + + +void __exit tpmif_exit(void) { exit_tpm_xenbus(); - cleanup_vtpm(); tpm_private_put(); gnttab_free_grant_references(gref_head); } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Wed Jul 05 20:11:37 2006 -0600 @@ -75,6 +75,9 @@ static unsigned long current_pages; static unsigned long current_pages; static unsigned long target_pages; +/* We increase/decrease in batches which fit in a page */ +static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)]; + /* VM /proc information for memory */ extern unsigned long totalram_pages; @@ -95,6 +98,11 @@ static void balloon_process(void *unused static void balloon_process(void *unused); static DECLARE_WORK(balloon_worker, balloon_process, NULL); static struct timer_list balloon_timer; + +/* When ballooning out (allocating memory to return to Xen) we don't really + want the kernel to try too hard since that can trigger the oom killer. */ +#define GFP_BALLOON \ + (GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC) #define PAGE_TO_LIST(p) (&(p)->lru) #define LIST_TO_PAGE(l) list_entry((l), struct page, lru) @@ -172,7 +180,7 @@ static unsigned long current_target(void static int increase_reservation(unsigned long nr_pages) { - unsigned long *frame_list, frame, pfn, i, flags; + unsigned long pfn, i, flags; struct page *page; long rc; struct xen_memory_reservation reservation = { @@ -181,15 +189,8 @@ static int increase_reservation(unsigned .domid = DOMID_SELF }; - if (nr_pages > (PAGE_SIZE / sizeof(unsigned long))) - nr_pages = PAGE_SIZE / sizeof(unsigned long); - - frame_list = (unsigned long *)__get_free_page(GFP_KERNEL); - if (frame_list == NULL) { - frame_list = &frame; - if (nr_pages > 1) - nr_pages = 1; - } + if (nr_pages > ARRAY_SIZE(frame_list)) + nr_pages = ARRAY_SIZE(frame_list); balloon_lock(flags); @@ -253,15 +254,12 @@ static int increase_reservation(unsigned out: balloon_unlock(flags); - if (frame_list != &frame) - free_page((unsigned long)frame_list); - return 0; } static int decrease_reservation(unsigned long nr_pages) { - unsigned long *frame_list, frame, pfn, i, flags; + unsigned long pfn, i, flags; struct page *page; void *v; int need_sleep = 0; @@ -272,18 +270,11 @@ static int decrease_reservation(unsigned .domid = DOMID_SELF }; - if (nr_pages > (PAGE_SIZE / sizeof(unsigned long))) - nr_pages = PAGE_SIZE / sizeof(unsigned long); - - frame_list = (unsigned long *)__get_free_page(GFP_KERNEL); - if (frame_list == NULL) { - frame_list = &frame; - if (nr_pages > 1) - nr_pages = 1; - } + if (nr_pages > ARRAY_SIZE(frame_list)) + nr_pages = ARRAY_SIZE(frame_list); for (i = 0; i < nr_pages; i++) { - if ((page = alloc_page(GFP_HIGHUSER)) == NULL) { + if ((page = alloc_page(GFP_BALLOON)) == NULL) { nr_pages = i; need_sleep = 1; break; @@ -330,9 +321,6 @@ static int decrease_reservation(unsigned totalram_pages = current_pages; balloon_unlock(flags); - - if (frame_list != &frame) - free_page((unsigned long)frame_list); return need_sleep; } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Wed Jul 05 20:11:37 2006 -0600 @@ -75,8 +75,6 @@ static void update_blkif_status(blkif_t /**************************************************************** * sysfs interface for VBD I/O requests */ - -#ifdef CONFIG_SYSFS #define VBD_SHOW(name, format, args...) \ static ssize_t show_##name(struct device *_dev, \ @@ -106,56 +104,39 @@ static struct attribute_group vbdstat_gr .attrs = vbdstat_attrs, }; +VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor); +VBD_SHOW(mode, "%s\n", be->mode); + int xenvbd_sysfs_addif(struct xenbus_device *dev) { - int error = 0; + int error; - error = sysfs_create_group(&dev->dev.kobj, - &vbdstat_group); + error = device_create_file(&dev->dev, &dev_attr_physical_device); + if (error) + goto fail1; + + error = device_create_file(&dev->dev, &dev_attr_mode); if (error) - goto fail; - + goto fail2; + + error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group); + if (error) + goto fail3; + return 0; - -fail: - sysfs_remove_group(&dev->dev.kobj, - &vbdstat_group); + +fail3: sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); +fail2: device_remove_file(&dev->dev, &dev_attr_mode); +fail1: device_remove_file(&dev->dev, &dev_attr_physical_device); return error; } void xenvbd_sysfs_delif(struct xenbus_device *dev) { - sysfs_remove_group(&dev->dev.kobj, - &vbdstat_group); -} - -#else - -#define xenvbd_sysfs_addif(dev) (0) -#define xenvbd_sysfs_delif(dev) ((void)0) - -#endif /* CONFIG_SYSFS */ - -static ssize_t show_physical_device(struct device *_dev, - struct device_attribute *attr, char *buf) -{ - struct xenbus_device *dev = to_xenbus_device(_dev); - struct backend_info *be = dev->dev.driver_data; - return sprintf(buf, "%x:%x\n", be->major, be->minor); -} -DEVICE_ATTR(physical_device, S_IRUSR | S_IRGRP | S_IROTH, - show_physical_device, NULL); - - -static ssize_t show_mode(struct device *_dev, struct device_attribute *attr, - char *buf) -{ - struct xenbus_device *dev = to_xenbus_device(_dev); - struct backend_info *be = dev->dev.driver_data; - return sprintf(buf, "%s\n", be->mode); -} -DEVICE_ATTR(mode, S_IRUSR | S_IRGRP | S_IROTH, show_mode, NULL); - + sysfs_remove_group(&dev->dev.kobj, &vbdstat_group); + device_remove_file(&dev->dev, &dev_attr_mode); + device_remove_file(&dev->dev, &dev_attr_physical_device); +} static int blkback_remove(struct xenbus_device *dev) { @@ -176,9 +157,8 @@ static int blkback_remove(struct xenbus_ be->blkif = NULL; } - device_remove_file(&dev->dev, &dev_attr_physical_device); - device_remove_file(&dev->dev, &dev_attr_mode); - xenvbd_sysfs_delif(dev); + if (be->major || be->minor) + xenvbd_sysfs_delif(dev); kfree(be); dev->dev.driver_data = NULL; @@ -293,15 +273,18 @@ static void backend_changed(struct xenbu err = vbd_create(be->blkif, handle, major, minor, (NULL == strchr(be->mode, 'w'))); if (err) { - be->major = 0; - be->minor = 0; + be->major = be->minor = 0; xenbus_dev_fatal(dev, err, "creating vbd structure"); return; } - device_create_file(&dev->dev, &dev_attr_physical_device); - device_create_file(&dev->dev, &dev_attr_mode); - xenvbd_sysfs_addif(dev); + err = xenvbd_sysfs_addif(dev); + if (err) { + vbd_free(&be->blkif->vbd); + be->major = be->minor = 0; + xenbus_dev_fatal(dev, err, "creating sysfs entries"); + return; + } /* We're potentially connected now */ update_blkif_status(be->blkif); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/console/console.c --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Jul 05 20:11:37 2006 -0600 @@ -267,7 +267,8 @@ void xencons_force_flush(void) /******************** User-space console driver (/dev/console) ************/ #define DRV(_d) (_d) -#define TTY_INDEX(_tty) ((_tty)->index) +#define DUMMY_TTY(_tty) ((xc_mode != XC_SERIAL) && \ + ((_tty)->index != (xc_num - 1))) static struct termios *xencons_termios[MAX_NR_CONSOLES]; static struct termios *xencons_termios_locked[MAX_NR_CONSOLES]; @@ -391,7 +392,7 @@ static void xencons_send_xchar(struct tt { unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; spin_lock_irqsave(&xencons_lock, flags); @@ -402,7 +403,7 @@ static void xencons_send_xchar(struct tt static void xencons_throttle(struct tty_struct *tty) { - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; if (I_IXOFF(tty)) @@ -411,7 +412,7 @@ static void xencons_throttle(struct tty_ static void xencons_unthrottle(struct tty_struct *tty) { - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; if (I_IXOFF(tty)) { @@ -426,7 +427,7 @@ static void xencons_flush_buffer(struct { unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; spin_lock_irqsave(&xencons_lock, flags); @@ -451,7 +452,7 @@ static int xencons_write( int i; unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return count; spin_lock_irqsave(&xencons_lock, flags); @@ -472,7 +473,7 @@ static void xencons_put_char(struct tty_ { unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; spin_lock_irqsave(&xencons_lock, flags); @@ -484,7 +485,7 @@ static void xencons_flush_chars(struct t { unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; spin_lock_irqsave(&xencons_lock, flags); @@ -496,7 +497,7 @@ static void xencons_wait_until_sent(stru { unsigned long orig_jiffies = jiffies; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; while (DRV(tty->driver)->chars_in_buffer(tty)) { @@ -515,7 +516,7 @@ static int xencons_open(struct tty_struc { unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return 0; spin_lock_irqsave(&xencons_lock, flags); @@ -532,7 +533,7 @@ static void xencons_close(struct tty_str { unsigned long flags; - if (TTY_INDEX(tty) != 0) + if (DUMMY_TTY(tty)) return; if (tty->count == 1) { @@ -588,8 +589,7 @@ static int __init xencons_init(void) DRV(xencons_driver)->init_termios = tty_std_termios; DRV(xencons_driver)->flags = TTY_DRIVER_REAL_RAW | - TTY_DRIVER_RESET_TERMIOS | - TTY_DRIVER_NO_DEVFS; + TTY_DRIVER_RESET_TERMIOS; DRV(xencons_driver)->termios = xencons_termios; DRV(xencons_driver)->termios_locked = xencons_termios_locked; @@ -599,8 +599,8 @@ static int __init xencons_init(void) DRV(xencons_driver)->name_base = 0 + xc_num; } else { DRV(xencons_driver)->name = "tty"; - DRV(xencons_driver)->minor_start = xc_num; - DRV(xencons_driver)->name_base = xc_num; + DRV(xencons_driver)->minor_start = 1; + DRV(xencons_driver)->name_base = 1; } tty_set_operations(xencons_driver, &xencons_ops); @@ -614,8 +614,6 @@ static int __init xencons_init(void) xencons_driver = NULL; return rc; } - - tty_register_device(xencons_driver, 0, NULL); if (xen_start_info->flags & SIF_INITDOMAIN) { xencons_priv_irq = bind_virq_to_irqhandler( @@ -629,8 +627,7 @@ static int __init xencons_init(void) } printk("Xen virtual console successfully installed as %s%d\n", - DRV(xencons_driver)->name, - DRV(xencons_driver)->name_base ); + DRV(xencons_driver)->name, xc_num); return 0; } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/core/evtchn.c --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c Wed Jul 05 20:11:37 2006 -0600 @@ -219,7 +219,10 @@ asmlinkage void evtchn_do_upcall(struct vcpu_info->evtchn_upcall_pending = 0; - /* NB. No need for a barrier here -- XCHG is a barrier on x86. */ +#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ + /* Clear master pending flag /before/ clearing selector flag. */ + rmb(); +#endif l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); while (l1 != 0) { l1i = __ffs(l1); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/core/gnttab.c --- a/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/gnttab.c Wed Jul 05 20:11:37 2006 -0600 @@ -169,7 +169,7 @@ int gnttab_end_foreign_access_ref(grant_ printk(KERN_ALERT "WARNING: g.e. still in use!\n"); return 0; } - } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != + } while ((nflags = synch_cmpxchg_subword(&shared[ref].flags, flags, 0)) != flags); return 1; @@ -224,7 +224,7 @@ unsigned long gnttab_end_foreign_transfe * reference and return failure (== 0). */ while (!((flags = shared[ref].flags) & GTF_transfer_committed)) { - if (synch_cmpxchg(&shared[ref].flags, flags, 0) == flags) + if (synch_cmpxchg_subword(&shared[ref].flags, flags, 0) == flags) return 0; cpu_relax(); } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c --- a/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_sysfs.c Wed Jul 05 20:11:37 2006 -0600 @@ -8,12 +8,14 @@ */ #include <linux/config.h> +#include <linux/err.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <asm/hypervisor.h> #include <xen/features.h> #include <xen/hypervisor_sysfs.h> +#include <xen/xenbus.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mike D. Day <ncmike@xxxxxxxxxx>"); @@ -95,6 +97,37 @@ static void xen_sysfs_version_destroy(vo static void xen_sysfs_version_destroy(void) { sysfs_remove_group(&hypervisor_subsys.kset.kobj, &version_group); +} + +/* UUID */ + +static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) +{ + char *vm, *val; + int ret; + + vm = xenbus_read(XBT_NIL, "vm", "", NULL); + if (IS_ERR(vm)) + return PTR_ERR(vm); + val = xenbus_read(XBT_NIL, vm, "uuid", NULL); + kfree(vm); + if (IS_ERR(val)) + return PTR_ERR(val); + ret = sprintf(buffer, "%s\n", val); + kfree(val); + return ret; +} + +HYPERVISOR_ATTR_RO(uuid); + +static int __init xen_sysfs_uuid_init(void) +{ + return sysfs_create_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr); +} + +static void xen_sysfs_uuid_destroy(void) +{ + sysfs_remove_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr); } /* xen compilation attributes */ @@ -314,10 +347,15 @@ static int __init hyper_sysfs_init(void) ret = xen_compilation_init(); if (ret) goto comp_out; + ret = xen_sysfs_uuid_init(); + if (ret) + goto uuid_out; ret = xen_properties_init(); if (!ret) goto out; + xen_sysfs_uuid_destroy(); +uuid_out: xen_compilation_destroy(); comp_out: xen_sysfs_version_destroy(); @@ -331,6 +369,7 @@ static void hyper_sysfs_exit(void) { xen_properties_destroy(); xen_compilation_destroy(); + xen_sysfs_uuid_destroy(); xen_sysfs_version_destroy(); xen_sysfs_type_destroy(); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Jul 05 20:11:37 2006 -0600 @@ -496,9 +496,9 @@ static void netbk_tx_err(netif_t *netif, do { make_tx_response(netif, txp, NETIF_RSP_ERROR); - if (++cons >= end) + if (cons >= end) break; - txp = RING_GET_REQUEST(&netif->tx, cons); + txp = RING_GET_REQUEST(&netif->tx, cons++); } while (1); netif->tx.req_cons = cons; netif_schedule_work(netif); @@ -663,6 +663,57 @@ static void netbk_fill_frags(struct sk_b } } +int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras, + int work_to_do) +{ + struct netif_extra_info *extra; + RING_IDX cons = netif->tx.req_cons; + + do { + if (unlikely(work_to_do-- <= 0)) { + DPRINTK("Missing extra info\n"); + return -EBADR; + } + + extra = (struct netif_extra_info *) + RING_GET_REQUEST(&netif->tx, cons); + if (unlikely(!extra->type || + extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) { + netif->tx.req_cons = ++cons; + DPRINTK("Invalid extra type: %d\n", extra->type); + return -EINVAL; + } + + memcpy(&extras[extra->type - 1], extra, sizeof(*extra)); + netif->tx.req_cons = ++cons; + } while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE); + + return work_to_do; +} + +static int netbk_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso) +{ + if (!gso->u.gso.size) { + DPRINTK("GSO size must not be zero.\n"); + return -EINVAL; + } + + /* Currently only TCPv4 S.O. is supported. */ + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { + DPRINTK("Bad GSO type %d.\n", gso->u.gso.type); + return -EINVAL; + } + + skb_shinfo(skb)->gso_size = gso->u.gso.size; + skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + + /* Header must be checked, and gso_segs computed. */ + skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; + skb_shinfo(skb)->gso_segs = 0; + + return 0; +} + /* Called after netfront has transmitted */ static void net_tx_action(unsigned long unused) { @@ -670,7 +721,7 @@ static void net_tx_action(unsigned long struct sk_buff *skb; netif_t *netif; netif_tx_request_t txreq; - struct netif_tx_extra txtra; + struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; u16 pending_idx; RING_IDX i; gnttab_map_grant_ref_t *mop; @@ -732,16 +783,15 @@ static void net_tx_action(unsigned long work_to_do--; netif->tx.req_cons = ++i; + memset(extras, 0, sizeof(extras)); if (txreq.flags & NETTXF_extra_info) { - if (work_to_do-- <= 0) { - DPRINTK("Missing extra info\n"); + work_to_do = netbk_get_extras(netif, extras, + work_to_do); + i = netif->tx.req_cons; + if (unlikely(work_to_do < 0)) { netbk_tx_err(netif, &txreq, i); continue; } - - memcpy(&txtra, RING_GET_REQUEST(&netif->tx, i), - sizeof(txtra)); - netif->tx.req_cons = ++i; } ret = netbk_count_requests(netif, &txreq, work_to_do); @@ -751,7 +801,7 @@ static void net_tx_action(unsigned long } i += ret; - if (unlikely(ret > MAX_SKB_FRAGS + 1)) { + if (unlikely(ret > MAX_SKB_FRAGS)) { DPRINTK("Too many frags\n"); netbk_tx_err(netif, &txreq, i); continue; @@ -788,10 +838,15 @@ static void net_tx_action(unsigned long /* Packets passed to netif_rx() must have some headroom. */ skb_reserve(skb, 16); - if (txreq.flags & NETTXF_gso) { - skb_shinfo(skb)->gso_size = txtra.u.gso.size; - skb_shinfo(skb)->gso_segs = txtra.u.gso.segs; - skb_shinfo(skb)->gso_type = txtra.u.gso.type; + if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) { + struct netif_extra_info *gso; + gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; + + if (netbk_set_skb_gso(skb, gso)) { + kfree_skb(skb); + netbk_tx_err(netif, &txreq, i); + continue; + } } gnttab_set_map_op(mop, MMAP_VADDR(pending_idx), diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Wed Jul 05 20:11:37 2006 -0600 @@ -101,11 +101,14 @@ static int netback_probe(struct xenbus_d goto abort_transaction; } - err = xenbus_printf(xbt, dev->nodename, "feature-tso", "%d", 1); +#if 0 /* KAF: After the protocol is finalised. */ + err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4", + "%d", 1); if (err) { - message = "writing feature-tso"; + message = "writing feature-gso-tcpv4"; goto abort_transaction; } +#endif err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Jul 05 20:11:37 2006 -0600 @@ -463,7 +463,7 @@ static int network_open(struct net_devic static inline int netfront_tx_slot_available(struct netfront_info *np) { - return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1; + return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 2; } static inline void network_maybe_wake_tx(struct net_device *dev) @@ -491,7 +491,13 @@ static void network_tx_buf_gc(struct net rmb(); /* Ensure we see responses up to 'rp'. */ for (cons = np->tx.rsp_cons; cons != prod; cons++) { - id = RING_GET_RESPONSE(&np->tx, cons)->id; + struct netif_tx_response *txrsp; + + txrsp = RING_GET_RESPONSE(&np->tx, cons); + if (txrsp->status == NETIF_RSP_NULL) + continue; + + id = txrsp->id; skb = np->tx_skbs[id]; if (unlikely(gnttab_query_foreign_access( np->grant_tx_ref[id]) != 0)) { @@ -719,6 +725,7 @@ static int network_start_xmit(struct sk_ unsigned short id; struct netfront_info *np = netdev_priv(dev); struct netif_tx_request *tx; + struct netif_extra_info *extra; char *data = skb->data; RING_IDX i; grant_ref_t ref; @@ -739,7 +746,8 @@ static int network_start_xmit(struct sk_ spin_lock_irq(&np->tx_lock); if (unlikely(!netif_carrier_ok(dev) || - (frags > 1 && !xennet_can_sg(dev)))) { + (frags > 1 && !xennet_can_sg(dev)) || + netif_needs_gso(dev, skb))) { spin_unlock_irq(&np->tx_lock); goto drop; } @@ -762,10 +770,29 @@ static int network_start_xmit(struct sk_ tx->size = len; tx->flags = 0; + extra = NULL; + if (skb->ip_summed == CHECKSUM_HW) /* local packet? */ tx->flags |= NETTXF_csum_blank | NETTXF_data_validated; if (skb->proto_data_valid) /* remote but checksummed? */ tx->flags |= NETTXF_data_validated; + + if (skb_shinfo(skb)->gso_size) { + struct netif_extra_info *gso = (struct netif_extra_info *) + RING_GET_REQUEST(&np->tx, ++i); + + if (extra) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + tx->flags |= NETTXF_extra_info; + + gso->u.gso.size = skb_shinfo(skb)->gso_size; + gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + + gso->type = XEN_NETIF_EXTRA_TYPE_GSO; + gso->flags = 0; + extra = gso; + } np->tx.req_prod_pvt = i + 1; @@ -1065,9 +1092,33 @@ static int xennet_set_sg(struct net_devi return ethtool_op_set_sg(dev, data); } +static int xennet_set_tso(struct net_device *dev, u32 data) +{ + if (data) { + struct netfront_info *np = netdev_priv(dev); + int val; + + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, + "feature-gso-tcpv4", "%d", &val) < 0) + val = 0; +#if 0 /* KAF: After the protocol is finalised. */ + if (!val) +#endif + return -ENOSYS; + } + + return ethtool_op_set_tso(dev, data); +} + static void xennet_set_features(struct net_device *dev) { - xennet_set_sg(dev, 1); + /* Turn off all GSO bits except ROBUST. */ + dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1; + dev->features |= NETIF_F_GSO_ROBUST; + xennet_set_sg(dev, 0); + + if (!xennet_set_sg(dev, 1)) + xennet_set_tso(dev, 1); } static void network_connect(struct net_device *dev) @@ -1148,6 +1199,8 @@ static struct ethtool_ops network_ethtoo .set_tx_csum = ethtool_op_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = xennet_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = xennet_set_tso, }; #ifdef CONFIG_SYSFS diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Wed Jul 05 20:11:37 2006 -0600 @@ -886,29 +886,6 @@ EXPORT_SYMBOL_GPL(unregister_xenstore_no EXPORT_SYMBOL_GPL(unregister_xenstore_notifier); -static int all_devices_ready_(struct device *dev, void *data) -{ - struct xenbus_device *xendev = to_xenbus_device(dev); - int *result = data; - - if (xendev->state != XenbusStateConnected) { - *result = 0; - return 1; - } - - return 0; -} - - -static int all_devices_ready(void) -{ - int ready = 1; - bus_for_each_dev(&xenbus_frontend.bus, NULL, &ready, - all_devices_ready_); - return ready; -} - - void xenbus_probe(void *unused) { BUG_ON((xenstored_ready <= 0)); @@ -1060,6 +1037,43 @@ postcore_initcall(xenbus_probe_init); postcore_initcall(xenbus_probe_init); +static int is_disconnected_device(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + + /* + * A device with no driver will never connect. We care only about + * devices which should currently be in the process of connecting. + */ + if (!dev->driver) + return 0; + + return (xendev->state != XenbusStateConnected); +} + +static int exists_disconnected_device(void) +{ + return bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, + is_disconnected_device); +} + +static int print_device_status(struct device *dev, void *data) +{ + struct xenbus_device *xendev = to_xenbus_device(dev); + + if (!dev->driver) { + /* Information only: is this too noisy? */ + printk(KERN_INFO "XENBUS: Device with no driver: %s\n", + xendev->nodename); + } else if (xendev->state != XenbusStateConnected) { + printk(KERN_WARNING "XENBUS: Timeout connecting " + "to device: %s (state %d)\n", + xendev->nodename, xendev->state); + } + + return 0; +} + /* * On a 10 second timeout, wait for all devices currently configured. We need * to do this to guarantee that the filesystems and / or network devices @@ -1081,13 +1095,12 @@ static int __init wait_for_devices(void) if (!is_running_on_xen()) return -ENODEV; - while (time_before(jiffies, timeout)) { - if (all_devices_ready()) - return 0; + while (time_before(jiffies, timeout) && exists_disconnected_device()) schedule_timeout_interruptible(HZ/10); - } - - printk(KERN_WARNING "XENBUS: Timeout connecting to devices!\n"); + + bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, + print_device_status); + return 0; } diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/synch_bitops.h Wed Jul 05 20:11:37 2006 -0600 @@ -138,4 +138,6 @@ static __inline__ int synch_var_test_bit synch_const_test_bit((nr),(addr)) : \ synch_var_test_bit((nr),(addr))) +#define synch_cmpxchg_subword synch_cmpxchg + #endif /* __XEN_SYNCH_BITOPS_H__ */ diff -r 26dae1c72cd9 -r 2b815d9acdea linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h --- a/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h Wed Jul 05 10:23:54 2006 -0600 +++ b/linux-2.6-xen-sparse/include/asm-ia64/synch_bitops.h Wed Jul 05 20:11:37 2006 -0600 @@ -58,4 +58,6 @@ static __inline__ int synch_var_test_bit synch_const_test_bit((nr),(addr)) : \ synch_var_test_bit((nr),(addr))) +#define synch_cmpxchg_subword synch_cmpxchg + #endif /* __XEN_SYNCH_BITOPS_H__ */ diff -r 26dae1c72cd9 -r 2b815d9acdea patches/linux-2.6.16.13/net-gso.patch --- a/patches/linux-2.6.16.13/net-gso.patch Wed Jul 05 10:23:54 2006 -0600 +++ b/patches/linux-2.6.16.13/net-gso.patch Wed Jul 05 20:11:37 2006 -0600 @@ -2225,7 +2225,7 @@ index d64e2ec..7494823 100644 err = ipcomp_compress(x, skb); iph = skb->nh.iph; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 00aa80e..84130c9 100644 +index 00aa80e..30c81a8 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -257,6 +257,7 @@ #include <linux/smp_lock.h> @@ -2281,7 +2281,7 @@ index 00aa80e..84130c9 100644 from += copy; copied += copy; -@@ -2026,6 +2021,71 @@ int tcp_getsockopt(struct sock *sk, int +@@ -2026,6 +2021,77 @@ int tcp_getsockopt(struct sock *sk, int } @@ -2306,12 +2306,18 @@ index 00aa80e..84130c9 100644 + if (!pskb_may_pull(skb, thlen)) + goto out; + -+ segs = NULL; -+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) -+ goto out; -+ + oldlen = (u16)~skb->len; + __skb_pull(skb, thlen); ++ ++ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { ++ /* Packet is from an untrusted source, reset gso_segs. */ ++ int mss = skb_shinfo(skb)->gso_size; ++ ++ skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; ++ ++ segs = NULL; ++ goto out; ++ } + + segs = skb_segment(skb, features); + if (IS_ERR(segs)) diff -r 26dae1c72cd9 -r 2b815d9acdea patches/linux-2.6.16.13/xenoprof-generic.patch --- a/patches/linux-2.6.16.13/xenoprof-generic.patch Wed Jul 05 10:23:54 2006 -0600 +++ b/patches/linux-2.6.16.13/xenoprof-generic.patch Wed Jul 05 20:11:37 2006 -0600 @@ -123,6 +123,21 @@ diff -pru ../pristine-linux-2.6.16.13/dr } } } +diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h ./drivers/oprofile/buffer_sync.h +--- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h 2006-05-03 05:38:44.000000000 +0800 ++++ ./drivers/oprofile/buffer_sync.h 2006-06-27 12:12:09.000000000 +0800 +@@ -9,6 +9,11 @@ + + #ifndef OPROFILE_BUFFER_SYNC_H + #define OPROFILE_BUFFER_SYNC_H ++ ++#define NO_DOMAIN_SWITCH -1 ++#define DOMAIN_SWITCH_START_EVENT1 0 ++#define DOMAIN_SWITCH_START_EVENT2 1 ++#define DOMAIN_SWITCH_STOP_EVENT1 2 + + /* add the necessary profiling hooks */ + int sync_start(void); diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c --- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-03 05:38:44.000000000 +0800 +++ ./drivers/oprofile/cpu_buffer.c 2006-06-19 22:43:53.000000000 +0800 diff -r 26dae1c72cd9 -r 2b815d9acdea tools/examples/Makefile --- a/tools/examples/Makefile Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/examples/Makefile Wed Jul 05 20:11:37 2006 -0600 @@ -26,7 +26,7 @@ XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd block-nbd -XEN_SCRIPTS += vtpm vtpm-delete +XEN_SCRIPTS += vtpm vtpm-delete vtpm-addtodb XEN_SCRIPTS += xen-hotplug-cleanup XEN_SCRIPTS += external-device-migrate XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh diff -r 26dae1c72cd9 -r 2b815d9acdea tools/examples/vtpm-common.sh --- a/tools/examples/vtpm-common.sh Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/examples/vtpm-common.sh Wed Jul 05 20:11:37 2006 -0600 @@ -347,16 +347,9 @@ function isLocalAddress() { # 2nd: name of the domain to migrate # 3rd: the migration step to perform function vtpm_migration_step() { - local instance res - instance=$(vtpmdb_find_instance $2) - if [ "$instance" == "" ]; then - echo "Error: Translation of domain name ($2) to instance failed. Check /etc/xen/vtpm.db" - log err "Error during translation of domain name" - else - res=$(isLocalAddress $1) - if [ "$res" == "0" ]; then - vtpm_migrate $1 $2 $3 - fi + local res=$(isLocalAddress $1) + if [ "$res" == "0" ]; then + vtpm_migrate $1 $2 $3 fi } diff -r 26dae1c72cd9 -r 2b815d9acdea tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/firmware/hvmloader/Makefile Wed Jul 05 20:11:37 2006 -0600 @@ -45,9 +45,9 @@ LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Tt .PHONY: all all: hvmloader -hvmloader: roms.h hvmloader.c acpi_madt.c - $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c - $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o +hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c + $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c + $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp diff -r 26dae1c72cd9 -r 2b815d9acdea tools/firmware/hvmloader/acpi_madt.c --- a/tools/firmware/hvmloader/acpi_madt.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/firmware/hvmloader/acpi_madt.c Wed Jul 05 20:11:37 2006 -0600 @@ -51,7 +51,7 @@ static int validate_hvm_info(struct hvm_ } /* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */ -static struct hvm_info_table * +struct hvm_info_table * get_hvm_info_table(void) { struct hvm_info_table *t; diff -r 26dae1c72cd9 -r 2b815d9acdea tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/firmware/hvmloader/hvmloader.c Wed Jul 05 20:11:37 2006 -0600 @@ -23,6 +23,7 @@ */ #include "roms.h" #include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */ +#include <xen/hvm/hvm_info_table.h> /* memory map */ #define VGABIOS_PHYSICAL_ADDRESS 0x000C0000 @@ -71,6 +72,8 @@ asm( extern int get_acpi_enabled(void); extern int acpi_madt_update(unsigned char* acpi_start); +extern void create_mp_tables(void); +struct hvm_info_table *get_hvm_info_table(void); static inline void outw(unsigned short addr, unsigned short val) @@ -162,10 +165,15 @@ int int main(void) { + struct hvm_info_table *t = get_hvm_info_table(); + puts("HVM Loader\n"); puts("Loading ROMBIOS ...\n"); memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios)); + if (t->apic_enabled) + create_mp_tables(); + if (cirrus_check()) { puts("Loading Cirrus VGABIOS ...\n"); memcpy((void *)VGABIOS_PHYSICAL_ADDRESS, diff -r 26dae1c72cd9 -r 2b815d9acdea tools/firmware/rombios/Makefile --- a/tools/firmware/rombios/Makefile Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/firmware/rombios/Makefile Wed Jul 05 20:11:37 2006 -0600 @@ -1,13 +1,9 @@ BIOS_BUILDS = BIOS-bochs-latest -BIOS_BUILDS = BIOS-bochs-latest -#BIOS_BUILDS += BIOS-bochs-2-processors -#BIOS_BUILDS += BIOS-bochs-4-processors -#BIOS_BUILDS += BIOS-bochs-8-processors .PHONY: all all: bios .PHONY: bios -bios: biossums ${BIOS_BUILDS} +bios: biossums BIOS-bochs-latest .PHONY: clean clean: @@ -26,36 +22,6 @@ BIOS-bochs-latest: rombios.c biossums ./biossums BIOS-bochs-latest rm -f _rombios_.s -BIOS-bochs-2-processors: rombios.c biossums - gcc -DBX_SMP_PROCESSORS=2 -E -P $< > _rombios2_.c - bcc -o rombios2.s -C-c -D__i86__ -0 -S _rombios2_.c - sed -e 's/^\.text//' -e 's/^\.data//' rombios2.s > _rombios2_.s - as86 _rombios2_.s -b tmp2.bin -u- -w- -g -0 -j -O -l rombios2.txt - -perl makesym.perl < rombios2.txt > rombios2.sym - mv tmp2.bin BIOS-bochs-2-processors - ./biossums BIOS-bochs-2-processors - rm -f _rombios2_.s - -BIOS-bochs-4-processors: rombios.c biossums - gcc -DBX_SMP_PROCESSORS=4 -E -P $< > _rombios4_.c - bcc -o rombios4.s -C-c -D__i86__ -0 -S _rombios4_.c - sed -e 's/^\.text//' -e 's/^\.data//' rombios4.s > _rombios4_.s - as86 _rombios4_.s -b tmp4.bin -u- -w- -g -0 -j -O -l rombios4.txt - -perl makesym.perl < rombios4.txt > rombios4.sym - mv tmp4.bin BIOS-bochs-4-processors - ./biossums BIOS-bochs-4-processors - rm -f _rombios4_.s - -BIOS-bochs-8-processors: rombios.c biossums - gcc -DBX_SMP_PROCESSORS=8 -E -P $< > _rombios8_.c - bcc -o rombios8.s -C-c -D__i86__ -0 -S _rombios8_.c - sed -e 's/^\.text//' -e 's/^\.data//' rombios8.s > _rombios8_.s - as86 _rombios8_.s -b tmp8.bin -u- -w- -g -0 -j -O -l rombios8.txt - -perl makesym.perl < rombios8.txt > rombios8.sym - mv tmp8.bin BIOS-bochs-8-processors - ./biossums BIOS-bochs-8-processors - rm -f _rombios8_.s - biossums: biossums.c gcc -o biossums biossums.c diff -r 26dae1c72cd9 -r 2b815d9acdea tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/firmware/rombios/rombios.c Wed Jul 05 20:11:37 2006 -0600 @@ -10514,6 +10514,34 @@ static Bit8u vgafont8[128*8]= 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, }; +#ifdef HVMASSIST +// +// MP Tables +// just carve out some blank space for HVMLOADER to write the MP tables to +// +// NOTE: There should be enough space for a 32 processor entry MP table +// +ASM_START +.org 0xcc00 +db 0x5F, 0x5F, 0x5F, 0x48, 0x56, 0x4D, 0x4D, 0x50 ;; ___HVMMP +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 128 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 192 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 256 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 320 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 384 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 448 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 512 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 576 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 640 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 704 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 768 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 832 bytes +dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 896 bytes +ASM_END + +#else // !HVMASSIST + ASM_START .org 0xcc00 // bcc-generated data will be placed here @@ -10835,3 +10863,5 @@ db 0,0,0,0 ;; MP feature bytes 2-5. #endif ASM_END + +#endif // HVMASSIST diff -r 26dae1c72cd9 -r 2b815d9acdea tools/ioemu/hw/piix4acpi.c --- a/tools/ioemu/hw/piix4acpi.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/ioemu/hw/piix4acpi.c Wed Jul 05 20:11:37 2006 -0600 @@ -476,6 +476,6 @@ void pci_piix4_acpi_init(PCIBus *bus) pci_register_io_region((PCIDevice *)d, 4, 0x10, PCI_ADDRESS_SPACE_IO, acpi_map); - pmtimer_state = pmtimer_init(); + /*pmtimer_state = pmtimer_init();*/ acpi_reset (d); } diff -r 26dae1c72cd9 -r 2b815d9acdea tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/libxc/xc_hvm_build.c Wed Jul 05 20:11:37 2006 -0600 @@ -4,6 +4,7 @@ #define ELFSIZE 32 #include <stddef.h> +#include <inttypes.h> #include "xg_private.h" #include "xc_elf.h" #include <stdlib.h> @@ -188,7 +189,7 @@ static int setup_guest(int xc_handle, unsigned char e820_map_nr; struct domain_setup_info dsi; - unsigned long long v_end; + uint64_t v_end; unsigned long shared_page_frame = 0; shared_iopage_t *sp; @@ -208,11 +209,11 @@ static int setup_guest(int xc_handle, v_end = (unsigned long long)memsize << 20; IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" - " Loaded HVM loader: %08lx->%08lx\n" - " TOTAL: %08lx->%016llx\n", + " Loaded HVM loader: %016"PRIx64"->%016"PRIx64"\n" + " TOTAL: %016"PRIx64"->%016"PRIx64"\n", dsi.v_kernstart, dsi.v_kernend, dsi.v_start, v_end); - IPRINTF(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry); + IPRINTF(" ENTRY ADDRESS: %016"PRIx64"\n", dsi.v_kernentry); if ( (v_end - dsi.v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) ) { diff -r 26dae1c72cd9 -r 2b815d9acdea tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/libxc/xc_linux_build.c Wed Jul 05 20:11:37 2006 -0600 @@ -12,6 +12,9 @@ #include <unistd.h> #include <inttypes.h> #include <zlib.h> + +/* Handy for printing out '0' prepended values at native pointer size */ +#define _p(a) ((void *) ((ulong)a)) #if defined(__i386__) #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) @@ -519,8 +522,6 @@ static int setup_guest(int xc_handle, goto error_out; } -#define _p(a) ((void *) (a)) - IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n" " Loaded kernel: %p->%p\n" " Init. ramdisk: %p->%p\n" @@ -795,9 +796,9 @@ static int setup_guest(int xc_handle, goto error_out; } -#define NR(_l,_h,_s) \ - (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ - ((_l) & ~((1UL<<(_s))-1))) >> (_s)) +#define NR(_l,_h,_s) \ + (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \ + ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s)) #if defined(__i386__) if ( dsi.pae_kernel != PAEKERN_no ) { @@ -825,8 +826,6 @@ static int setup_guest(int xc_handle, break; #endif } - -#define _p(a) ((void *) (a)) IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"); IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart), @@ -848,8 +847,8 @@ static int setup_guest(int xc_handle, if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages ) { PERROR("Initial guest OS requires too much space\n" - "(%luMB is greater than %luMB limit)\n", - (v_end-dsi.v_start)>>20, nr_pages>>(20-PAGE_SHIFT)); + "(%pMB is greater than %luMB limit)\n", + _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT)); goto error_out; } @@ -1083,7 +1082,8 @@ static int setup_guest(int xc_handle, if ( hypercall_pfn >= nr_pages ) goto error_out; op.u.hypercall_init.domain = (domid_t)dom; - op.u.hypercall_init.mfn = page_array[hypercall_pfn]; + op.u.hypercall_init.gmfn = shadow_mode_enabled ? + hypercall_pfn : page_array[hypercall_pfn]; op.cmd = DOM0_HYPERCALL_INIT; if ( xc_dom0_op(xc_handle, &op) ) goto error_out; diff -r 26dae1c72cd9 -r 2b815d9acdea tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/libxc/xc_linux_save.c Wed Jul 05 20:11:37 2006 -0600 @@ -415,11 +415,11 @@ static int suspend_and_state(int (*suspe ** which entries do not require canonicalization (in particular, those ** entries which map the virtual address reserved for the hypervisor). */ -void canonicalize_pagetable(unsigned long type, unsigned long pfn, - const void *spage, void *dpage) -{ - - int i, pte_last, xen_start, xen_end; +int canonicalize_pagetable(unsigned long type, unsigned long pfn, + const void *spage, void *dpage) +{ + + int i, pte_last, xen_start, xen_end, race = 0; uint64_t pte; /* @@ -481,7 +481,8 @@ void canonicalize_pagetable(unsigned lon is quite feasible under live migration */ DPRINTF("PT Race: [%08lx,%d] pte=%llx, mfn=%08lx\n", type, i, (unsigned long long)pte, mfn); - pfn = 0; /* zap it - we'll retransmit this page later */ + pfn = 0; /* zap it - we'll retransmit this page later */ + race = 1; /* inform the caller of race; fatal if !live */ } else pfn = mfn_to_pfn(mfn); @@ -496,7 +497,7 @@ void canonicalize_pagetable(unsigned lon } - return; + return race; } @@ -567,7 +568,7 @@ int xc_linux_save(int xc_handle, int io_ int rc = 1, i, j, last_iter, iter = 0; int live = (flags & XCFLAGS_LIVE); int debug = (flags & XCFLAGS_DEBUG); - int sent_last_iter, skip_this_iter; + int race = 0, sent_last_iter, skip_this_iter; /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; @@ -1000,7 +1001,11 @@ int xc_linux_save(int xc_handle, int io_ if (pagetype >= L1TAB && pagetype <= L4TAB) { /* We have a pagetable page: need to rewrite it. */ - canonicalize_pagetable(pagetype, pfn, spage, page); + race = + canonicalize_pagetable(pagetype, pfn, spage, page); + + if(race && !live) + goto out; if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) { ERR("Error when writing to state file (4)"); diff -r 26dae1c72cd9 -r 2b815d9acdea tools/libxc/xc_load_elf.c --- a/tools/libxc/xc_load_elf.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/libxc/xc_load_elf.c Wed Jul 05 20:11:37 2006 -0600 @@ -68,7 +68,7 @@ static int parseelfimage(const char *ima Elf_Ehdr *ehdr = (Elf_Ehdr *)image; Elf_Phdr *phdr; Elf_Shdr *shdr; - unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base, elf_pa_off; + Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_base, elf_pa_off; const char *shstrtab; char *guestinfo=NULL, *p; int h, virt_base_defined, elf_pa_off_defined; @@ -162,15 +162,19 @@ static int parseelfimage(const char *ima /* Initial guess for virt_base is 0 if it is not explicitly defined. */ p = strstr(guestinfo, "VIRT_BASE="); virt_base_defined = (p != NULL); - virt_base = virt_base_defined ? strtoul(p+10, &p, 0) : 0; + virt_base = virt_base_defined ? strtoull(p+10, &p, 0) : 0; /* Initial guess for elf_pa_off is virt_base if not explicitly defined. */ p = strstr(guestinfo, "ELF_PADDR_OFFSET="); elf_pa_off_defined = (p != NULL); - elf_pa_off = elf_pa_off_defined ? strtoul(p+17, &p, 0) : virt_base; + elf_pa_off = elf_pa_off_defined ? strtoull(p+17, &p, 0) : virt_base; if ( elf_pa_off_defined && !virt_base_defined ) - goto bad_image; + { + ERROR("Neither ELF_PADDR_OFFSET nor VIRT_BASE found in __xen_guest" + " section."); + return -EINVAL; + } for ( h = 0; h < ehdr->e_phnum; h++ ) { @@ -179,7 +183,11 @@ static int parseelfimage(const char *ima continue; vaddr = phdr->p_paddr - elf_pa_off + virt_base; if ( (vaddr + phdr->p_memsz) < vaddr ) - goto bad_image; + { + ERROR("ELF program header %d is too large.", h); + return -EINVAL; + } + if ( vaddr < kernstart ) kernstart = vaddr; if ( (vaddr + phdr->p_memsz) > kernend ) @@ -196,13 +204,16 @@ static int parseelfimage(const char *ima dsi->v_kernentry = ehdr->e_entry; if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL ) - dsi->v_kernentry = strtoul(p+11, &p, 0); + dsi->v_kernentry = strtoull(p+11, &p, 0); if ( (kernstart > kernend) || (dsi->v_kernentry < kernstart) || (dsi->v_kernentry > kernend) || (dsi->v_start > kernstart) ) - goto bad_image; + { + ERROR("ELF start or entries are out of bounds."); + return -EINVAL; + } if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) dsi->load_symtab = 1; @@ -214,10 +225,6 @@ static int parseelfimage(const char *ima loadelfsymtab(image, 0, 0, NULL, dsi); return 0; - - bad_image: - ERROR("Malformed ELF image."); - return -EINVAL; } static int diff -r 26dae1c72cd9 -r 2b815d9acdea tools/libxc/xc_private.c --- a/tools/libxc/xc_private.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/libxc/xc_private.c Wed Jul 05 20:11:37 2006 -0600 @@ -26,7 +26,7 @@ unsigned int get_pfn_type(int xc_handle, { DECLARE_DOM0_OP; op.cmd = DOM0_GETPAGEFRAMEINFO; - op.u.getpageframeinfo.mfn = mfn; + op.u.getpageframeinfo.gmfn = mfn; op.u.getpageframeinfo.domain = (domid_t)dom; if ( do_dom0_op(xc_handle, &op) < 0 ) { diff -r 26dae1c72cd9 -r 2b815d9acdea tools/libxc/xg_private.h --- a/tools/libxc/xg_private.h Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/libxc/xg_private.h Wed Jul 05 20:11:37 2006 -0600 @@ -132,13 +132,13 @@ typedef unsigned long l4_pgentry_t; struct domain_setup_info { - unsigned long v_start; - unsigned long v_end; - unsigned long v_kernstart; - unsigned long v_kernend; - unsigned long v_kernentry; - - unsigned long elf_paddr_offset; + uint64_t v_start; + uint64_t v_end; + uint64_t v_kernstart; + uint64_t v_kernend; + uint64_t v_kernentry; + + uint64_t elf_paddr_offset; #define PAEKERN_no 0 #define PAEKERN_yes 1 diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xend/XendLogging.py --- a/tools/python/xen/xend/XendLogging.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xend/XendLogging.py Wed Jul 05 20:11:37 2006 -0600 @@ -43,7 +43,7 @@ BACKUP_COUNT = 5 BACKUP_COUNT = 5 STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" -LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" +LOGFILE_FORMAT = "[%(asctime)s %(name)s %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s" DATE_FORMAT = "%Y-%m-%d %H:%M:%S" diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/cfgbootpolicy.py --- a/tools/python/xen/xm/cfgbootpolicy.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/cfgbootpolicy.py Wed Jul 05 20:11:37 2006 -0600 @@ -22,8 +22,6 @@ import traceback import traceback import tempfile import os, stat -import re -import commands import shutil import string from xen.util.security import ACMError, err diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/create.py Wed Jul 05 20:11:37 2006 -0600 @@ -21,11 +21,8 @@ """ import os import os.path -import string import sys import socket -import commands -import time import re import xmlrpclib diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/dumppolicy.py --- a/tools/python/xen/xm/dumppolicy.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/dumppolicy.py Wed Jul 05 20:11:37 2006 -0600 @@ -19,10 +19,6 @@ """ import sys import traceback -import os -import commands -import shutil -import string from xen.util.security import ACMError, err, dump_policy diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/labels.py --- a/tools/python/xen/xm/labels.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/labels.py Wed Jul 05 20:11:37 2006 -0600 @@ -20,9 +20,6 @@ """ import sys import traceback -import os -import commands -import shutil import string from xen.util.security import ACMError, err, list_labels, active_policy from xen.util.security import vm_label_re, res_label_re, all_label_re diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/loadpolicy.py --- a/tools/python/xen/xm/loadpolicy.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/loadpolicy.py Wed Jul 05 20:11:37 2006 -0600 @@ -20,10 +20,6 @@ """ import sys import traceback -import os -import commands -import shutil -import string from xen.util.security import ACMError, err, load_policy diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/main.py Wed Jul 05 20:11:37 2006 -0600 @@ -556,7 +556,7 @@ def xm_vcpu_list(args): def xm_reboot(args): - arg_check(args, "reboot", 1, 4) + arg_check(args, "reboot", 1, 3) from xen.xm import shutdown shutdown.main(["shutdown", "-R"] + args) diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/makepolicy.py --- a/tools/python/xen/xm/makepolicy.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/makepolicy.py Wed Jul 05 20:11:37 2006 -0600 @@ -19,10 +19,6 @@ """ import sys import traceback -import os -import commands -import shutil -import string from xen.util.security import ACMError, err, make_policy diff -r 26dae1c72cd9 -r 2b815d9acdea tools/python/xen/xm/shutdown.py --- a/tools/python/xen/xm/shutdown.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/python/xen/xm/shutdown.py Wed Jul 05 20:11:37 2006 -0600 @@ -17,8 +17,6 @@ """Domain shutdown. """ -import string -import sys import time from xen.xend.XendClient import server @@ -92,7 +90,8 @@ def main_all(opts, args): shutdown(opts, None, mode, opts.vals.wait) def main_dom(opts, args): - if len(args) < 1: opts.err('Missing domain') + if len(args) == 0: opts.err('No domain parameter given') + if len(args) > 1: opts.err('No multiple domain parameters allowed') dom = args[0] mode = shutdown_mode(opts) shutdown(opts, [ dom ], mode, opts.vals.wait) diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xenmon/xenmon.py --- a/tools/xenmon/xenmon.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xenmon/xenmon.py Wed Jul 05 20:11:37 2006 -0600 @@ -36,6 +36,7 @@ import sys # constants NSAMPLES = 100 NDOMAINS = 32 +IDLE_DOMAIN = 31 # idle domain's ID # the struct strings for qos_info ST_DOM_INFO = "6Q4i32s" @@ -253,6 +254,14 @@ def display(scr, row, col, str, attr=0): sys.exit(1) +# diplay domain id +def display_domain_id(scr, row, col, dom): + if dom == IDLE_DOMAIN: + display(scr, row, col-1, "Idle") + else: + display(scr, row, col, "%d" % dom) + + # the live monitoring code def show_livestats(cpu): ncpu = 1 # number of cpu's on this platform @@ -361,7 +370,7 @@ def show_livestats(cpu): # display gotten row += 1 col = 2 - display(stdscr, row, col, "%d" % dom) + display_domain_id(stdscr, row, col, dom) col += 4 display(stdscr, row, col, "%s" % time_scale(h2[dom][0][0])) col += 12 @@ -386,7 +395,7 @@ def show_livestats(cpu): if options.allocated: row += 1 col = 2 - display(stdscr, row, col, "%d" % dom) + display_domain_id(stdscr, row, col, dom) col += 28 display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][1])) col += 42 @@ -398,7 +407,7 @@ def show_livestats(cpu): if options.blocked: row += 1 col = 2 - display(stdscr, row, col, "%d" % dom) + display_domain_id(stdscr, row, col, dom) col += 4 display(stdscr, row, col, "%s" % time_scale(h2[dom][2][0])) col += 12 @@ -418,7 +427,7 @@ def show_livestats(cpu): if options.waited: row += 1 col = 2 - display(stdscr, row, col, "%d" % dom) + display_domain_id(stdscr, row, col, dom) col += 4 display(stdscr, row, col, "%s" % time_scale(h2[dom][3][0])) col += 12 @@ -438,7 +447,7 @@ def show_livestats(cpu): if options.excount: row += 1 col = 2 - display(stdscr, row, col, "%d" % dom) + display_domain_id(stdscr, row, col, dom) col += 28 display(stdscr, row, col, "%d/s" % h2[dom][4]) @@ -451,7 +460,7 @@ def show_livestats(cpu): if options.iocount: row += 1 col = 2 - display(stdscr, row, col, "%d" % dom) + display_domain_id(stdscr, row, col, dom) col += 4 display(stdscr, row, col, "%d/s" % h2[dom][5][0]) col += 24 @@ -558,7 +567,10 @@ def writelog(): curr = last = time.time() outfiles = {} for dom in range(0, NDOMAINS): - outfiles[dom] = Delayed("%s-dom%d.log" % (options.prefix, dom), 'w') + if dom == IDLE_DOMAIN: + outfiles[dom] = Delayed("%s-idle.log" % options.prefix, 'w') + else: + outfiles[dom] = Delayed("%s-dom%d.log" % (options.prefix, dom), 'w') outfiles[dom].delayed_write("# passed cpu dom cpu(tot) cpu(%) cpu/ex allocated/ex blocked(tot) blocked(%) blocked/io waited(tot) waited(%) waited/ex ex/s io(tot) io/ex\n") while options.duration == 0 or interval < (options.duration * 1000): diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xenstat/libxenstat/src/xenstat.c --- a/tools/xenstat/libxenstat/src/xenstat.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xenstat/libxenstat/src/xenstat.c Wed Jul 05 20:11:37 2006 -0600 @@ -20,6 +20,11 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#include <linux/compiler.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/types.h> +#include <sys/stat.h> #include <xs.h> #include "xenstat.h" @@ -36,6 +41,7 @@ struct xenstat_handle { struct xs_handle *xshandle; /* xenstore handle */ int page_size; FILE *procnetdev; + DIR *sysfsvbd; char xen_version[VERSION_SIZE]; /* xen version running on this node */ }; @@ -62,6 +68,8 @@ struct xenstat_domain { unsigned int ssid; unsigned int num_networks; xenstat_network *networks; /* Array of length num_networks */ + unsigned int num_vbds; + xenstat_vbd *vbds; }; struct xenstat_vcpu { @@ -82,6 +90,15 @@ struct xenstat_network { unsigned long long terrs; unsigned long long tdrop; }; + +struct xenstat_vbd { + unsigned int dev; + unsigned long long oo_reqs; + unsigned long long rd_reqs; + unsigned long long wr_reqs; +}; +#define SYSFS_VBD_PATH "/sys/devices/xen-backend/" + /* * Data-collection types @@ -108,12 +125,15 @@ static int xenstat_collect_vcpus(xensta static int xenstat_collect_vcpus(xenstat_node * node); static int xenstat_collect_networks(xenstat_node * node); static int xenstat_collect_xen_version(xenstat_node * node); +static int xenstat_collect_vbds(xenstat_node * node); static void xenstat_free_vcpus(xenstat_node * node); static void xenstat_free_networks(xenstat_node * node); static void xenstat_free_xen_version(xenstat_node * node); +static void xenstat_free_vbds(xenstat_node * node); static void xenstat_uninit_vcpus(xenstat_handle * handle); static void xenstat_uninit_networks(xenstat_handle * handle); static void xenstat_uninit_xen_version(xenstat_handle * handle); +static void xenstat_uninit_vbds(xenstat_handle * handle); static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id); static xenstat_collector collectors[] = { @@ -122,7 +142,9 @@ static xenstat_collector collectors[] = { XENSTAT_NETWORK, xenstat_collect_networks, xenstat_free_networks, xenstat_uninit_networks }, { XENSTAT_XEN_VERSION, xenstat_collect_xen_version, - xenstat_free_xen_version, xenstat_uninit_xen_version } + xenstat_free_xen_version, xenstat_uninit_xen_version }, + { XENSTAT_VBD, xenstat_collect_vbds, + xenstat_free_vbds, xenstat_uninit_vbds } }; #define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector)) @@ -259,6 +281,8 @@ xenstat_node *xenstat_get_node(xenstat_h domain->ssid = domaininfo[i].ssidref; domain->num_networks = 0; domain->networks = NULL; + domain->num_vbds = 0; + domain->vbds = NULL; domain++; } @@ -448,6 +472,21 @@ xenstat_network *xenstat_domain_network( { if (domain->networks && 0 <= network && network < domain->num_networks) return &(domain->networks[network]); + return NULL; +} + +/* Get the number of VBDs for a given domain */ +unsigned int xenstat_domain_num_vbds(xenstat_domain * domain) +{ + return domain->num_vbds; +} + +/* Get the VBD handle to obtain VBD stats */ +xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain, + unsigned int vbd) +{ + if (domain->vbds && 0 <= vbd && vbd < domain->num_vbds) + return &(domain->vbds[vbd]); return NULL; } @@ -710,6 +749,139 @@ static void xenstat_uninit_xen_version(x { } +/* + * VBD functions + */ + +static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap) +{ + static char file_name[80]; + int fd, num_read; + + sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what); + fd = open(file_name, O_RDONLY, 0); + if (fd==-1) return -1; + num_read = read(fd, ret, cap - 1); + close(fd); + if (num_read<=0) return -1; + ret[num_read] = '\0'; + return num_read; +} + +/* Collect information about VBDs */ +static int xenstat_collect_vbds(xenstat_node * node) +{ + struct dirent *dp; + + if (node->handle->sysfsvbd == NULL) { + node->handle->sysfsvbd = opendir(SYSFS_VBD_PATH); + if (node->handle->sysfsvbd == NULL) { + perror("Error opening " SYSFS_VBD_PATH); + return 0; + } + } + + rewinddir(node->handle->sysfsvbd); + + for(dp = readdir(node->handle->sysfsvbd); dp != NULL ; + dp = readdir(node->handle->sysfsvbd)) { + xenstat_domain *domain; + xenstat_vbd vbd; + unsigned int domid; + int ret; + char buf[256]; + + + ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev); + if (ret != 2) { + continue; + } + printf("%s is VBD.\n",dp->d_name); + + domain = xenstat_node_domain(node, domid); + if (domain == NULL) { + fprintf(stderr, + "Found interface vbd-%u-%u but domain %u" + " does not exist.\n", + domid, vbd.dev, domid); + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1)) + { + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1)) + { + continue; + } + + if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0) + || ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1)) + { + continue; + } + + + if (domain->vbds == NULL) { + domain->num_vbds = 1; + domain->vbds = malloc(sizeof(xenstat_vbd)); + } else { + domain->num_vbds++; + domain->vbds = realloc(domain->vbds, + domain->num_vbds * + sizeof(xenstat_vbd)); + } + if (domain->vbds == NULL) + return 0; + domain->vbds[domain->num_vbds - 1] = vbd; + } + + return 1; +} + +/* Free VBD information */ +static void xenstat_free_vbds(xenstat_node * node) +{ + unsigned int i; + for (i = 0; i < node->num_domains; i++) + free(node->domains[i].vbds); +} + +/* Free VBD information in handle */ +static void xenstat_uninit_vbds(xenstat_handle * handle) +{ + if (handle->sysfsvbd) + closedir(handle->sysfsvbd); +} + +/* Get the major number of VBD device */ +unsigned int xenstat_vbd_dev(xenstat_vbd * vbd) +{ + return vbd->dev; +} + +/* Get the number of OO(Out of) requests */ +unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd) +{ + return vbd->oo_reqs; +} + +/* Get the number of READ requests */ +unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd) +{ + return vbd->rd_reqs; +} + +/* Get the number of WRITE requests */ +unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd) +{ + return vbd->wr_reqs; +} + static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id) { char path[80]; diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xenstat/libxenstat/src/xenstat.h --- a/tools/xenstat/libxenstat/src/xenstat.h Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xenstat/libxenstat/src/xenstat.h Wed Jul 05 20:11:37 2006 -0600 @@ -23,6 +23,7 @@ typedef struct xenstat_node xenstat_node typedef struct xenstat_node xenstat_node; typedef struct xenstat_vcpu xenstat_vcpu; typedef struct xenstat_network xenstat_network; +typedef struct xenstat_vbd xenstat_vbd; /* Initialize the xenstat library. Returns a handle to be used with * subsequent calls to the xenstat library, or NULL if an error occurs. */ @@ -35,7 +36,8 @@ void xenstat_uninit(xenstat_handle * han #define XENSTAT_VCPU 0x1 #define XENSTAT_NETWORK 0x2 #define XENSTAT_XEN_VERSION 0x4 -#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK|XENSTAT_XEN_VERSION) +#define XENSTAT_VBD 0x8 +#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK|XENSTAT_XEN_VERSION|XENSTAT_VBD) /* Get all available information about a node */ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags); @@ -117,6 +119,13 @@ xenstat_network *xenstat_domain_network( xenstat_network *xenstat_domain_network(xenstat_domain * domain, unsigned int network); +/* Get the number of VBDs for a given domain */ +unsigned int xenstat_domain_num_vbds(xenstat_domain *); + +/* Get the VBD handle to obtain VBD stats */ +xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain, + unsigned int vbd); + /* * VCPU functions - extract information from a xenstat_vcpu */ @@ -156,3 +165,14 @@ unsigned long long xenstat_network_terrs /* Get the number of transmit drops for this network */ unsigned long long xenstat_network_tdrop(xenstat_network * network); + +/* + * VBD functions - extract information from a xen_vbd + */ +/* Get the device number for Virtual Block Device */ +unsigned int xenstat_vbd_dev(xenstat_vbd * vbd); + +/* Get the number of OO/RD/WR requests for vbd */ +unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd); +unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd); +unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd); diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xenstat/xentop/xentop.c --- a/tools/xenstat/xentop/xentop.c Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xenstat/xentop/xentop.c Wed Jul 05 20:11:37 2006 -0600 @@ -27,6 +27,7 @@ #include <sys/time.h> #include <time.h> #include <unistd.h> +#include <linux/kdev_t.h> #include <xenstat.h> @@ -65,6 +66,7 @@ static int compare(unsigned long long, u static int compare(unsigned long long, unsigned long long); static int compare_domains(xenstat_domain **, xenstat_domain **); static unsigned long long tot_net_bytes( xenstat_domain *, int); +static unsigned long long tot_vbd_reqs( xenstat_domain *, int); /* Field functions */ static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2); @@ -91,6 +93,15 @@ static void print_ssid(xenstat_domain *d static void print_ssid(xenstat_domain *domain); static int compare_name(xenstat_domain *domain1, xenstat_domain *domain2); static void print_name(xenstat_domain *domain); +static int compare_vbds(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbds(xenstat_domain *domain); +static int compare_vbd_oo(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbd_oo(xenstat_domain *domain); +static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbd_rd(xenstat_domain *domain); +static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2); +static void print_vbd_wr(xenstat_domain *domain); + /* Section printing functions */ static void do_summary(void); @@ -99,6 +110,7 @@ static void do_domain(xenstat_domain *); static void do_domain(xenstat_domain *); static void do_vcpu(xenstat_domain *); static void do_network(xenstat_domain *); +static void do_vbd(xenstat_domain *); static void top(void); /* Field types */ @@ -116,6 +128,10 @@ typedef enum field_id { FIELD_NETS, FIELD_NET_TX, FIELD_NET_RX, + FIELD_VBDS, + FIELD_VBD_OO, + FIELD_VBD_RD, + FIELD_VBD_WR, FIELD_SSID } field_id; @@ -140,6 +156,10 @@ field fields[] = { { FIELD_NETS, "NETS", 4, compare_nets, print_nets }, { FIELD_NET_TX, "NETTX(k)", 8, compare_net_tx, print_net_tx }, { FIELD_NET_RX, "NETRX(k)", 8, compare_net_rx, print_net_rx }, + { FIELD_VBDS, "VBDS", 4, compare_vbds, print_vbds }, + { FIELD_VBD_OO, "VBD_OO", 8, compare_vbd_oo, print_vbd_oo }, + { FIELD_VBD_RD, "VBD_RD", 8, compare_vbd_rd, print_vbd_rd }, + { FIELD_VBD_WR, "VBD_WR", 8, compare_vbd_wr, print_vbd_wr }, { FIELD_SSID, "SSID", 4, compare_ssid, print_ssid } }; @@ -158,6 +178,7 @@ unsigned int iterations = 0; unsigned int iterations = 0; int show_vcpus = 0; int show_networks = 0; +int show_vbds = 0; int repeat_header = 0; #define PROMPT_VAL_LEN 80 char *prompt = NULL; @@ -180,6 +201,7 @@ static void usage(const char *program) "-V, --version output version information and exit\n" "-d, --delay=SECONDS seconds between updates (default 3)\n" "-n, --networks output vif network data\n" + "-b, --vbds output vbd block device data\n" "-r, --repeat-header repeat table header before each domain\n" "-v, --vcpus output vcpu data\n" "-b, --batch output in batch mode, no user input accepted\n" @@ -289,6 +311,9 @@ static int handle_key(int ch) switch(ch) { case 'n': case 'N': show_networks ^= 1; + break; + case 'b': case 'B': + show_vbds ^= 1; break; case 'r': case 'R': repeat_header ^= 1; @@ -585,6 +610,96 @@ static unsigned long long tot_net_bytes( return total; } +/* Compares number of virtual block devices of two domains, + returning -1,0,1 for * <,=,> */ +static int compare_vbds(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(xenstat_domain_num_vbds(domain1), + xenstat_domain_num_vbds(domain2)); +} + +/* Prints number of virtual block devices statistic */ +static void print_vbds(xenstat_domain *domain) +{ + print("%4u", xenstat_domain_num_vbds(domain)); +} + +/* Compares number of total VBD OO requests of two domains, + returning -1,0,1 * for <,=,> */ +static int compare_vbd_oo(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_vbd_reqs(domain1, FIELD_VBD_OO), + tot_vbd_reqs(domain2, FIELD_VBD_OO)); +} + +/* Prints number of total VBD OO requests statistic */ +static void print_vbd_oo(xenstat_domain *domain) +{ + print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_OO)); +} + +/* Compares number of total VBD READ requests of two domains, + returning -1,0,1 * for <,=,> */ +static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_vbd_reqs(domain1, FIELD_VBD_RD), + tot_vbd_reqs(domain2, FIELD_VBD_RD)); +} + +/* Prints number of total VBD READ requests statistic */ +static void print_vbd_rd(xenstat_domain *domain) +{ + print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_RD)); +} + +/* Compares number of total VBD WRITE requests of two domains, + returning -1,0,1 * for <,=,> */ +static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2) +{ + return -compare(tot_vbd_reqs(domain1,FIELD_VBD_WR), + tot_vbd_reqs(domain2,FIELD_VBD_WR)); +} + +/* Prints number of total VBD WRITE requests statistic */ +static void print_vbd_wr(xenstat_domain *domain) +{ + print("%8llu", tot_vbd_reqs(domain,FIELD_VBD_WR)); +} + +/* Gets number of total VBD requests statistic, + * if flag is FIELD_VBD_OO, then OO requests, + * if flag is FIELD_VBD_RD, then READ requests and + * if flag is FIELD_VBD_WR, then WRITE requests. + */ +static unsigned long long tot_vbd_reqs(xenstat_domain *domain, int flag) +{ + int i = 0; + xenstat_vbd *vbd; + unsigned num_vbds = 0; + unsigned long long total = 0; + + num_vbds = xenstat_domain_num_vbds(domain); + + for ( i=0 ; i < num_vbds ; i++) { + vbd = xenstat_domain_vbd(domain,i); + switch(flag) { + case FIELD_VBD_OO: + total += xenstat_vbd_oo_reqs(vbd); + break; + case FIELD_VBD_RD: + total += xenstat_vbd_rd_reqs(vbd); + break; + case FIELD_VBD_WR: + total += xenstat_vbd_wr_reqs(vbd); + break; + default: + break; + } + } + + return total; +} + /* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */ static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2) { @@ -680,6 +795,13 @@ void do_bottom_line(void) addch(A_REVERSE | 'N'); attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks"); addstr(" "); + + /* VBDs */ + attr_addstr(show_vbds ? COLOR_PAIR(1) : 0, "v"); + addch(A_REVERSE | 'B'); + attr_addstr(show_vbds ? COLOR_PAIR(1) : 0, "ds"); + addstr(" "); + /* vcpus */ addch(A_REVERSE | 'V'); @@ -769,6 +891,28 @@ void do_network(xenstat_domain *domain) } } + +/* Output all VBD information */ +void do_vbd(xenstat_domain *domain) +{ + int i = 0; + xenstat_vbd *vbd; + unsigned num_vbds = 0; + + num_vbds = xenstat_domain_num_vbds(domain); + + for (i=0 ; i< num_vbds; i++) { + vbd = xenstat_domain_vbd(domain,i); + + print("VBD %4u [%2x:%2x] OO: %8llu RD: %8llu WR: %8llu\n", + xenstat_vbd_dev(vbd), + MAJOR(xenstat_vbd_dev(vbd)), MINOR(xenstat_vbd_dev(vbd)), + xenstat_vbd_oo_reqs(vbd), + xenstat_vbd_rd_reqs(vbd), + xenstat_vbd_wr_reqs(vbd)); + } +} + static void top(void) { xenstat_domain **domains; @@ -812,6 +956,8 @@ static void top(void) do_vcpu(domains[i]); if (show_networks) do_network(domains[i]); + if (show_vbds) + do_vbd(domains[i]); } if(!batch) @@ -827,6 +973,7 @@ int main(int argc, char **argv) { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "networks", no_argument, NULL, 'n' }, + { "vbds", no_argument, NULL, 'x' }, { "repeat-header", no_argument, NULL, 'r' }, { "vcpus", no_argument, NULL, 'v' }, { "delay", required_argument, NULL, 'd' }, @@ -834,7 +981,7 @@ int main(int argc, char **argv) { "iterations", required_argument, NULL, 'i' }, { 0, 0, 0, 0 }, }; - const char *sopts = "hVbnvd:bi:"; + const char *sopts = "hVnxrvd:bi:"; if (atexit(cleanup) != 0) fail("Failed to install cleanup handler.\n"); @@ -851,6 +998,9 @@ int main(int argc, char **argv) exit(0); case 'n': show_networks = 1; + break; + case 'x': + show_vbds = 1; break; case 'r': repeat_header = 1; diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py --- a/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xm-test/tests/vtpm/02_vtpm-cat_pcrs.py Wed Jul 05 20:11:37 2006 -0600 @@ -14,16 +14,15 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() try: console = domain.start() except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -33,11 +32,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xm-test/tests/vtpm/03_vtpm-susp_res.py --- a/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xm-test/tests/vtpm/03_vtpm-susp_res.py Wed Jul 05 20:11:37 2006 -0600 @@ -15,6 +15,7 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() consoleHistory = "" try: @@ -22,10 +23,8 @@ except DomainError, e: except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -35,11 +34,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) @@ -48,50 +47,59 @@ consoleHistory = console.getHistory() consoleHistory = console.getHistory() domain.closeConsole() -try: - status, ouptut = traceCommand("xm save %s %s.save" % - (domName, domName), - timeout=30) +loop = 0 +while loop < 3: + try: + status, ouptut = traceCommand("xm save %s %s.save" % + (domName, domName), + timeout=30) -except TimeoutError, e: - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL(str(e)) + except TimeoutError, e: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) -if status != 0: - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL("xm save did not succeed") + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm save did not succeed") -try: - status, ouptut = traceCommand("xm restore %s.save" % - (domName), - timeout=30) -except TimeoutError, e: + try: + status, ouptut = traceCommand("xm restore %s.save" % + (domName), + timeout=30) + except TimeoutError, e: + os.remove("%s.save" % domName) + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL(str(e)) + os.remove("%s.save" % domName) - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL(str(e)) -os.remove("%s.save" % domName) + if status != 0: + saveLog(consoleHistory) + vtpm_cleanup(domName) + FAIL("xm restore did not succeed") -if status != 0: - saveLog(consoleHistory) - vtpm_cleanup(domName) - FAIL("xm restore did not succeed") + try: + console = domain.getConsole() + except ConsoleError, e: + vtpm_cleanup(domName) + FAIL(str(e)) -try: - console = domain.getConsole() -except ConsoleError, e: - vtpm_cleanup(domName) - FAIL(str(e)) + try: + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") + except ConsoleError, e: + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL(str(e)) -try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") -except ConsoleError, e: - saveLog(console.getHistory()) - vtpm_cleanup(domName) - FAIL(str(e)) + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + + loop += 1 domain.closeConsole() @@ -99,5 +107,3 @@ domain.stop() vtpm_cleanup(domName) -if not re.search("PCR-00:",run["output"]): - FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py --- a/tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xm-test/tests/vtpm/04_vtpm-loc_migr.py Wed Jul 05 20:11:37 2006 -0600 @@ -16,6 +16,7 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() consoleHistory = "" try: @@ -23,10 +24,8 @@ except DomainError, e: except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -36,11 +35,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) @@ -83,11 +82,17 @@ while loop < 3: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + loop += 1 domain.closeConsole() @@ -95,6 +100,3 @@ domain.stop() domain.stop() vtpm_cleanup(domName) - -if not re.search("PCR-00:",run["output"]): - FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py --- a/tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xm-test/tests/vtpm/05_vtpm-loc_migr.py Wed Jul 05 20:11:37 2006 -0600 @@ -16,6 +16,7 @@ import os.path config = {"vtpm":"instance=1,backend=0"} domain = XmTestDomain(extraConfig=config) +domName = domain.getName() consoleHistory = "" try: @@ -23,10 +24,8 @@ except DomainError, e: except DomainError, e: if verbose: print e.extra - vtpm_cleanup(domain.getName()) - FAIL("Unable to create domain") - -domName = domain.getName() + vtpm_cleanup(domName) + FAIL("Unable to create domain (%s)" % domName) try: console.sendInput("input") @@ -36,11 +35,11 @@ except ConsoleError, e: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") if re.search("No such file",run["output"]): vtpm_cleanup(domName) @@ -83,11 +82,17 @@ while loop < 3: FAIL(str(e)) try: - run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs") + run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs") except ConsoleError, e: saveLog(console.getHistory()) vtpm_cleanup(domName) - FAIL(str(e)) + FAIL("No result from dumping the PCRs") + + if not re.search("PCR-00:",run["output"]): + saveLog(console.getHistory()) + vtpm_cleanup(domName) + FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") + loop += 1 domain.closeConsole() @@ -95,6 +100,3 @@ domain.stop() domain.stop() vtpm_cleanup(domName) - -if not re.search("PCR-00:",run["output"]): - FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side") diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xm-test/tests/vtpm/Makefile.am --- a/tools/xm-test/tests/vtpm/Makefile.am Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xm-test/tests/vtpm/Makefile.am Wed Jul 05 20:11:37 2006 -0600 @@ -4,7 +4,10 @@ TESTS = 01_vtpm-list_pos.test \ 02_vtpm-cat_pcrs.test \ 03_vtpm-susp_res.test \ 04_vtpm-loc_migr.test \ - 05_vtpm-loc_migr.test + 05_vtpm-loc_migr.test \ + 06_vtpm-susp_res_pcrs.test \ + 07_vtpm-mig_pcrs.test \ + 08_vtpm-mig_pcrs.test XFAIL_TESTS = diff -r 26dae1c72cd9 -r 2b815d9acdea tools/xm-test/tests/vtpm/vtpm_utils.py --- a/tools/xm-test/tests/vtpm/vtpm_utils.py Wed Jul 05 10:23:54 2006 -0600 +++ b/tools/xm-test/tests/vtpm/vtpm_utils.py Wed Jul 05 20:11:37 2006 -0600 @@ -16,4 +16,4 @@ if output == "": FAIL("virtual TPM manager must be started to run this test") def vtpm_cleanup(domName): - traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName) + traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/ia64/xen/dom0_ops.c Wed Jul 05 20:11:37 2006 -0600 @@ -36,7 +36,7 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_ case DOM0_GETPAGEFRAMEINFO: { struct page_info *page; - unsigned long mfn = op->u.getpageframeinfo.mfn; + unsigned long mfn = op->u.getpageframeinfo.gmfn; domid_t dom = op->u.getpageframeinfo.domain; struct domain *d; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/ia64/xen/xensetup.c --- a/xen/arch/ia64/xen/xensetup.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/ia64/xen/xensetup.c Wed Jul 05 20:11:37 2006 -0600 @@ -425,8 +425,9 @@ void start_kernel(void) scheduler_init(); idle_vcpu[0] = (struct vcpu*) ia64_r13; - idle_domain = domain_create(IDLE_DOMAIN_ID, 0); - BUG_ON(idle_domain == NULL); + idle_domain = domain_create(IDLE_DOMAIN_ID); + if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) ) + BUG(); late_setup_arch(&cmdline); alloc_dom_xen_and_dom_io(); @@ -503,9 +504,8 @@ printk("num_online_cpus=%d, max_cpus=%d\ } /* Create initial domain 0. */ - dom0 = domain_create(0, 0); - - if ( dom0 == NULL ) + dom0 = domain_create(0); + if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) ) panic("Error creating domain 0\n"); set_bit(_DOMF_privileged, &dom0->domain_flags); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/dom0_ops.c --- a/xen/arch/x86/dom0_ops.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/dom0_ops.c Wed Jul 05 20:11:37 2006 -0600 @@ -207,7 +207,7 @@ long arch_do_dom0_op(struct dom0_op *op, case DOM0_GETPAGEFRAMEINFO: { struct page_info *page; - unsigned long mfn = op->u.getpageframeinfo.mfn; + unsigned long mfn = op->u.getpageframeinfo.gmfn; domid_t dom = op->u.getpageframeinfo.domain; struct domain *d; @@ -407,14 +407,16 @@ long arch_do_dom0_op(struct dom0_op *op, case DOM0_HYPERCALL_INIT: { - struct domain *d; - unsigned long mfn = op->u.hypercall_init.mfn; + struct domain *d = find_domain_by_id(op->u.hypercall_init.domain); + unsigned long gmfn = op->u.hypercall_init.gmfn; + unsigned long mfn; void *hypercall_page; ret = -ESRCH; - if ( unlikely((d = find_domain_by_id( - op->u.hypercall_init.domain)) == NULL) ) - break; + if ( unlikely(d == NULL) ) + break; + + mfn = gmfn_to_mfn(d, gmfn); ret = -EACCES; if ( !mfn_valid(mfn) || diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/domain.c Wed Jul 05 20:11:37 2006 -0600 @@ -67,16 +67,11 @@ static void default_idle(void) void idle_loop(void) { - int cpu = smp_processor_id(); - for ( ; ; ) { page_scrub_schedule_work(); - default_idle(); - - if ( softirq_pending(cpu) ) - do_softirq(); + do_softirq(); } } @@ -956,7 +951,7 @@ void domain_relinquish_resources(struct } } - if ( hvm_guest(d->vcpu[0]) ) + if ( d->vcpu[0] && hvm_guest(d->vcpu[0]) ) hvm_relinquish_guest_resources(d); shadow_mode_disable(d); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/hvm/svm/svm.c Wed Jul 05 20:11:37 2006 -0600 @@ -962,8 +962,8 @@ static void svm_vmexit_do_cpuid(struct v !vlapic_global_enabled((VLAPIC(v))) ) { /* Since the apic is disabled, avoid any confusion - about SMP cpus being available */ - clear_bit(X86_FEATURE_APIC, &edx); + about SMP cpus being available */ + clear_bit(X86_FEATURE_APIC, &edx); } #if CONFIG_PAGING_LEVELS < 3 @@ -974,52 +974,51 @@ static void svm_vmexit_do_cpuid(struct v if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 ) { if ( !v->domain->arch.hvm_domain.pae_enabled ) - { - clear_bit(X86_FEATURE_PAE, &edx); - } + clear_bit(X86_FEATURE_PAE, &edx); clear_bit(X86_FEATURE_PSE, &edx); clear_bit(X86_FEATURE_PSE36, &edx); } -#endif +#endif /* Clear out reserved bits. */ ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED; edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED; clear_bit(X86_FEATURE_MWAIT & 31, &ecx); - /* Guest should only see one logical processor. - * See details on page 23 of AMD CPUID Specification. - */ - clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */ - ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ - ebx |= 0x00010000; /* set to 1 just for precaution */ - - /* Disable machine check architecture */ - clear_bit(X86_FEATURE_MCA, &edx); - clear_bit(X86_FEATURE_MCE, &edx); - } - else if ( ( input > 0x00000005 ) && ( input < 0x80000000 ) ) - { - eax = ebx = ecx = edx = 0x0; + /* Guest should only see one logical processor. + * See details on page 23 of AMD CPUID Specification. + */ + clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */ + ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */ + ebx |= 0x00010000; /* set to 1 just for precaution */ + + /* Disable machine check architecture */ + clear_bit(X86_FEATURE_MCA, &edx); + clear_bit(X86_FEATURE_MCE, &edx); + } + else if ( (input > 0x00000005) && (input < 0x80000000) ) + { + if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) ) + eax = ebx = ecx = edx = 0; } else if ( input == 0x80000001 ) { - /* We duplicate some CPUID_00000001 code because many bits of - CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */ + /* We duplicate some CPUID_00000001 code because many bits of + CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */ if ( !hvm_apic_support(v->domain) || - !vlapic_global_enabled((VLAPIC(v))) ) + !vlapic_global_enabled((VLAPIC(v))) ) { /* Since the apic is disabled, avoid any confusion - about SMP cpus being available */ - clear_bit(X86_FEATURE_APIC, &edx); - } - - /* Clear the Cmp_Legacy bit - * This bit is supposed to be zero when HTT = 0. - * See details on page 23 of AMD CPUID Specification. - */ - clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx); + about SMP cpus being available */ + clear_bit(X86_FEATURE_APIC, &edx); + } + + /* Clear the Cmp_Legacy bit + * This bit is supposed to be zero when HTT = 0. + * See details on page 23 of AMD CPUID Specification. + */ + clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx); #ifdef __i386__ /* Mask feature for Intel ia32e or AMD long mode. */ @@ -1030,7 +1029,7 @@ static void svm_vmexit_do_cpuid(struct v #endif #if CONFIG_PAGING_LEVELS < 3 - clear_bit(X86_FEATURE_NX & 31, &edx); + clear_bit(X86_FEATURE_NX & 31, &edx); clear_bit(X86_FEATURE_PAE, &edx); clear_bit(X86_FEATURE_PSE, &edx); clear_bit(X86_FEATURE_PSE36, &edx); @@ -1039,29 +1038,29 @@ static void svm_vmexit_do_cpuid(struct v { if ( !v->domain->arch.hvm_domain.pae_enabled ) { - clear_bit(X86_FEATURE_NX & 31, &edx); - clear_bit(X86_FEATURE_PAE, &edx); + clear_bit(X86_FEATURE_NX & 31, &edx); + clear_bit(X86_FEATURE_PAE, &edx); } clear_bit(X86_FEATURE_PSE, &edx); clear_bit(X86_FEATURE_PSE36, &edx); } -#endif +#endif /* Make SVM feature invisible to the guest. */ clear_bit(X86_FEATURE_SVME & 31, &ecx); - - /* So far, we do not support 3DNow for the guest. */ - clear_bit(X86_FEATURE_3DNOW & 31, &edx); - clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); + + /* So far, we do not support 3DNow for the guest. */ + clear_bit(X86_FEATURE_3DNOW & 31, &edx); + clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); } else if ( ( input == 0x80000007 ) || ( input == 0x8000000A ) ) { - /* Mask out features of power management and SVM extension. */ - eax = ebx = ecx = edx = 0; + /* Mask out features of power management and SVM extension. */ + eax = ebx = ecx = edx = 0; } else if ( input == 0x80000008 ) { - ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */ + ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */ } regs->eax = (unsigned long)eax; @@ -1214,8 +1213,9 @@ static void svm_dr_access (struct vcpu * } -static void svm_get_prefix_info(struct vmcb_struct *vmcb, - unsigned int dir, segment_selector_t **seg, unsigned int *asize) +static void svm_get_prefix_info( + struct vmcb_struct *vmcb, + unsigned int dir, segment_selector_t **seg, unsigned int *asize) { unsigned char inst[MAX_INST_LEN]; int i; @@ -1287,9 +1287,10 @@ static void svm_get_prefix_info(struct v /* Get the address of INS/OUTS instruction */ -static inline int svm_get_io_address(struct vcpu *v, - struct cpu_user_regs *regs, unsigned int dir, - unsigned long *count, unsigned long *addr) +static inline int svm_get_io_address( + struct vcpu *v, + struct cpu_user_regs *regs, unsigned int dir, + unsigned long *count, unsigned long *addr) { unsigned long reg; unsigned int asize = 0; @@ -2697,9 +2698,9 @@ asmlinkage void svm_vmexit_handler(struc if (exit_reason == -1) { + svm_dump_vmcb(__func__, vmcb); printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n", __func__); - BUG(); domain_crash_synchronous(); } diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Wed Jul 05 20:11:37 2006 -0600 @@ -36,38 +36,57 @@ #include <xen/kernel.h> #include <asm/shadow.h> #include <xen/keyhandler.h> + #if CONFIG_PAGING_LEVELS >= 3 #include <asm/shadow_64.h> #endif -int vmcs_size; - -struct vmcs_struct *vmx_alloc_vmcs(void) +static int vmcs_size; +static int vmcs_order; +static u32 vmcs_revision_id; + +void vmx_init_vmcs_config(void) +{ + u32 vmx_msr_low, vmx_msr_high; + + if ( vmcs_size ) + return; + + rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); + + vmcs_revision_id = vmx_msr_low; + + vmcs_size = vmx_msr_high & 0x1fff; + vmcs_order = get_order_from_bytes(vmcs_size); +} + +static struct vmcs_struct *vmx_alloc_vmcs(void) { struct vmcs_struct *vmcs; - u32 vmx_msr_low, vmx_msr_high; - - rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); - vmcs_size = vmx_msr_high & 0x1fff; - vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size)); - memset((char *)vmcs, 0, vmcs_size); /* don't remove this */ - - vmcs->vmcs_revision_id = vmx_msr_low; + + if ( (vmcs = alloc_xenheap_pages(vmcs_order)) == NULL ) + { + DPRINTK("Failed to allocate VMCS.\n"); + return NULL; + } + + memset(vmcs, 0, vmcs_size); /* don't remove this */ + vmcs->vmcs_revision_id = vmcs_revision_id; + return vmcs; } -static void free_vmcs(struct vmcs_struct *vmcs) -{ - int order; - - order = get_order_from_bytes(vmcs_size); - free_xenheap_pages(vmcs, order); +static void vmx_free_vmcs(struct vmcs_struct *vmcs) +{ + free_xenheap_pages(vmcs, vmcs_order); } static void __vmx_clear_vmcs(void *info) { struct vcpu *v = info; + __vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs)); + v->arch.hvm_vmx.active_cpu = -1; v->arch.hvm_vmx.launched = 0; } @@ -127,11 +146,19 @@ void vmx_vmcs_exit(struct vcpu *v) vcpu_unpause(v); } +struct vmcs_struct *vmx_alloc_host_vmcs(void) +{ + return vmx_alloc_vmcs(); +} + +void vmx_free_host_vmcs(struct vmcs_struct *vmcs) +{ + vmx_free_vmcs(vmcs); +} + static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx) { int error = 0; - void *io_bitmap_a; - void *io_bitmap_b; error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL, MONITOR_PIN_BASED_EXEC_CONTROLS); @@ -140,19 +167,8 @@ static inline int construct_vmcs_control error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS); - /* need to use 0x1000 instead of PAGE_SIZE */ - io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000)); - io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000)); - memset(io_bitmap_a, 0xff, 0x1000); - /* don't bother debug port access */ - clear_bit(PC_DEBUG_PORT, io_bitmap_a); - memset(io_bitmap_b, 0xff, 0x1000); - - error |= __vmwrite(IO_BITMAP_A, (u64) virt_to_maddr(io_bitmap_a)); - error |= __vmwrite(IO_BITMAP_B, (u64) virt_to_maddr(io_bitmap_b)); - - arch_vmx->io_bitmap_a = io_bitmap_a; - arch_vmx->io_bitmap_b = io_bitmap_b; + error |= __vmwrite(IO_BITMAP_A, (u64)virt_to_maddr(arch_vmx->io_bitmap_a)); + error |= __vmwrite(IO_BITMAP_B, (u64)virt_to_maddr(arch_vmx->io_bitmap_b)); return error; } @@ -428,84 +444,71 @@ static inline int construct_vmcs_host(vo } /* - * Need to extend to support full virtualization. + * the working VMCS pointer has been set properly + * just before entering this function. */ static int construct_vmcs(struct vcpu *v, cpu_user_regs_t *regs) { struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx; int error; - long rc; - - memset(arch_vmx, 0, sizeof(struct arch_vmx_struct)); - - spin_lock_init(&arch_vmx->vmcs_lock); - arch_vmx->active_cpu = -1; - - /* - * Create a new VMCS - */ - if (!(arch_vmx->vmcs = vmx_alloc_vmcs())) { - printk("Failed to create a new VMCS\n"); + + if ( (error = construct_vmcs_controls(arch_vmx)) ) { + printk("construct_vmcs: construct_vmcs_controls failed.\n"); + return error; + } + + /* host selectors */ + if ( (error = construct_vmcs_host()) ) { + printk("construct_vmcs: construct_vmcs_host failed.\n"); + return error; + } + + /* guest selectors */ + if ( (error = construct_init_vmcs_guest(regs)) ) { + printk("construct_vmcs: construct_vmcs_guest failed.\n"); + return error; + } + + if ( (error = __vmwrite(EXCEPTION_BITMAP, + MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) { + printk("construct_vmcs: setting exception bitmap failed.\n"); + return error; + } + + if ( regs->eflags & EF_TF ) + error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + else + error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); + + return error; +} + +int vmx_create_vmcs(struct vcpu *v) +{ + if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL ) return -ENOMEM; - } + __vmx_clear_vmcs(v); + return 0; +} + +void vmx_destroy_vmcs(struct vcpu *v) +{ + struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx; + + if ( arch_vmx->vmcs == NULL ) + return; vmx_clear_vmcs(v); - vmx_load_vmcs(v); - - if ((error = construct_vmcs_controls(arch_vmx))) { - printk("construct_vmcs: construct_vmcs_controls failed\n"); - rc = -EINVAL; - goto err_out; - } - - /* host selectors */ - if ((error = construct_vmcs_host())) { - printk("construct_vmcs: construct_vmcs_host failed\n"); - rc = -EINVAL; - goto err_out; - } - - /* guest selectors */ - if ((error = construct_init_vmcs_guest(regs))) { - printk("construct_vmcs: construct_vmcs_guest failed\n"); - rc = -EINVAL; - goto err_out; - } - - if ((error |= __vmwrite(EXCEPTION_BITMAP, - MONITOR_DEFAULT_EXCEPTION_BITMAP))) { - printk("construct_vmcs: setting Exception bitmap failed\n"); - rc = -EINVAL; - goto err_out; - } - - if (regs->eflags & EF_TF) - __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); - else - __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB); - - return 0; - -err_out: - vmx_destroy_vmcs(v); - return rc; -} - -void vmx_destroy_vmcs(struct vcpu *v) -{ - struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx; - - vmx_clear_vmcs(v); - - free_vmcs(arch_vmx->vmcs); + + free_xenheap_pages(arch_vmx->io_bitmap_a, IO_BITMAP_ORDER); + free_xenheap_pages(arch_vmx->io_bitmap_b, IO_BITMAP_ORDER); + + arch_vmx->io_bitmap_a = NULL; + arch_vmx->io_bitmap_b = NULL; + + vmx_free_vmcs(arch_vmx->vmcs); arch_vmx->vmcs = NULL; - - free_xenheap_pages(arch_vmx->io_bitmap_a, get_order_from_bytes(0x1000)); - arch_vmx->io_bitmap_a = NULL; - - free_xenheap_pages(arch_vmx->io_bitmap_b, get_order_from_bytes(0x1000)); - arch_vmx->io_bitmap_b = NULL; } void vm_launch_fail(unsigned long eflags) @@ -544,19 +547,20 @@ void arch_vmx_do_resume(struct vcpu *v) void arch_vmx_do_launch(struct vcpu *v) { - int error; cpu_user_regs_t *regs = ¤t->arch.guest_context.user_regs; - error = construct_vmcs(v, regs); - if ( error < 0 ) + vmx_load_vmcs(v); + + if ( construct_vmcs(v, regs) < 0 ) { - if (v->vcpu_id == 0) { - printk("Failed to construct a new VMCS for BSP.\n"); + if ( v->vcpu_id == 0 ) { + printk("Failed to construct VMCS for BSP.\n"); } else { - printk("Failed to construct a new VMCS for AP %d\n", v->vcpu_id); + printk("Failed to construct VMCS for AP %d.\n", v->vcpu_id); } domain_crash_synchronous(); } + vmx_do_launch(v); reset_stack_and_jump(vmx_asm_do_vmentry); } diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jul 05 20:11:37 2006 -0600 @@ -54,34 +54,73 @@ static void vmx_ctxt_switch_from(struct static void vmx_ctxt_switch_from(struct vcpu *v); static void vmx_ctxt_switch_to(struct vcpu *v); -void vmx_final_setup_guest(struct vcpu *v) -{ +static int vmx_initialize_guest_resources(struct vcpu *v) +{ + struct domain *d = v->domain; + struct vcpu *vc; + void *io_bitmap_a, *io_bitmap_b; + int rc; + v->arch.schedule_tail = arch_vmx_do_launch; v->arch.ctxt_switch_from = vmx_ctxt_switch_from; v->arch.ctxt_switch_to = vmx_ctxt_switch_to; - if ( v->vcpu_id == 0 ) - { - struct domain *d = v->domain; - struct vcpu *vc; - + if ( v->vcpu_id != 0 ) + return 1; + + for_each_vcpu ( d, vc ) + { /* Initialize monitor page table */ - for_each_vcpu(d, vc) - vc->arch.monitor_table = pagetable_null(); - - /* - * Required to do this once per domain - * XXX todo: add a seperate function to do these. - */ - memset(&d->shared_info->evtchn_mask[0], 0xff, - sizeof(d->shared_info->evtchn_mask)); - - /* Put the domain in shadow mode even though we're going to be using - * the shared 1:1 page table initially. It shouldn't hurt */ - shadow_mode_enable(d, - SHM_enable|SHM_refcounts| - SHM_translate|SHM_external|SHM_wr_pt_pte); - } + vc->arch.monitor_table = pagetable_null(); + + memset(&vc->arch.hvm_vmx, 0, sizeof(struct arch_vmx_struct)); + + if ( (rc = vmx_create_vmcs(vc)) != 0 ) + { + DPRINTK("Failed to create VMCS for vcpu %d: err=%d.\n", + vc->vcpu_id, rc); + return 0; + } + + spin_lock_init(&vc->arch.hvm_vmx.vmcs_lock); + + if ( (io_bitmap_a = alloc_xenheap_pages(IO_BITMAP_ORDER)) == NULL ) + { + DPRINTK("Failed to allocate io bitmap b for vcpu %d.\n", + vc->vcpu_id); + return 0; + } + + if ( (io_bitmap_b = alloc_xenheap_pages(IO_BITMAP_ORDER)) == NULL ) + { + DPRINTK("Failed to allocate io bitmap b for vcpu %d.\n", + vc->vcpu_id); + return 0; + } + + memset(io_bitmap_a, 0xff, 0x1000); + memset(io_bitmap_b, 0xff, 0x1000); + + /* don't bother debug port access */ + clear_bit(PC_DEBUG_PORT, io_bitmap_a); + + vc->arch.hvm_vmx.io_bitmap_a = io_bitmap_a; + vc->arch.hvm_vmx.io_bitmap_b = io_bitmap_b; + } + + /* + * Required to do this once per domain XXX todo: add a seperate function + * to do these. + */ + memset(&d->shared_info->evtchn_mask[0], 0xff, + sizeof(d->shared_info->evtchn_mask)); + + /* Put the domain in shadow mode even though we're going to be using + * the shared 1:1 page table initially. It shouldn't hurt */ + shadow_mode_enable( + d, SHM_enable|SHM_refcounts|SHM_translate|SHM_external|SHM_wr_pt_pte); + + return 1; } static void vmx_relinquish_guest_resources(struct domain *d) @@ -90,9 +129,9 @@ static void vmx_relinquish_guest_resourc for_each_vcpu ( d, v ) { + vmx_destroy_vmcs(v); if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) continue; - vmx_destroy_vmcs(v); free_monitor_pagetable(v); kill_timer(&v->arch.hvm_vmx.hlt_timer); if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) ) @@ -442,12 +481,6 @@ void stop_vmx(void) { if (read_cr4() & X86_CR4_VMXE) __vmxoff(); -} - -int vmx_initialize_guest_resources(struct vcpu *v) -{ - vmx_final_setup_guest(v); - return 1; } void vmx_migrate_timers(struct vcpu *v) @@ -638,58 +671,61 @@ static int check_vmx_controls(u32 ctrls, int start_vmx(void) { + u32 eax, edx; struct vmcs_struct *vmcs; - u32 ecx; - u32 eax, edx; - u64 phys_vmcs; /* debugging */ /* * Xen does not fill x86_capability words except 0. */ - ecx = cpuid_ecx(1); - boot_cpu_data.x86_capability[4] = ecx; + boot_cpu_data.x86_capability[4] = cpuid_ecx(1); if (!(test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability))) return 0; rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx); - if (eax & IA32_FEATURE_CONTROL_MSR_LOCK) { - if ((eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0) { + if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK ) + { + if ( (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0 ) + { printk("VMX disabled by Feature Control MSR.\n"); return 0; } } - else { + else + { wrmsr(IA32_FEATURE_CONTROL_MSR, IA32_FEATURE_CONTROL_MSR_LOCK | IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0); } - if (!check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, - MSR_IA32_VMX_PINBASED_CTLS_MSR)) + if ( !check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, + MSR_IA32_VMX_PINBASED_CTLS_MSR) ) return 0; - if (!check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, - MSR_IA32_VMX_PROCBASED_CTLS_MSR)) + if ( !check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, + MSR_IA32_VMX_PROCBASED_CTLS_MSR) ) return 0; - if (!check_vmx_controls(MONITOR_VM_EXIT_CONTROLS, - MSR_IA32_VMX_EXIT_CTLS_MSR)) + if ( !check_vmx_controls(MONITOR_VM_EXIT_CONTROLS, + MSR_IA32_VMX_EXIT_CTLS_MSR) ) return 0; - if (!check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, - MSR_IA32_VMX_ENTRY_CTLS_MSR)) + if ( !check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, + MSR_IA32_VMX_ENTRY_CTLS_MSR) ) return 0; - set_in_cr4(X86_CR4_VMXE); /* Enable VMXE */ - - if (!(vmcs = vmx_alloc_vmcs())) { - printk("Failed to allocate VMCS\n"); + set_in_cr4(X86_CR4_VMXE); + + vmx_init_vmcs_config(); + + if ( (vmcs = vmx_alloc_host_vmcs()) == NULL ) + { + printk("Failed to allocate host VMCS\n"); return 0; } - phys_vmcs = (u64) virt_to_maddr(vmcs); - - if (__vmxon(phys_vmcs)) { + if ( __vmxon(virt_to_maddr(vmcs)) ) + { printk("VMXON failed\n"); + vmx_free_host_vmcs(vmcs); return 0; } @@ -832,7 +868,7 @@ static void vmx_vmexit_do_cpuid(struct c cpuid_count(input, count, &eax, &ebx, &ecx, &edx); eax &= NUM_CORES_RESET_MASK; } - else + else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) ) { cpuid(input, &eax, &ebx, &ecx, &edx); @@ -857,10 +893,14 @@ static void vmx_vmexit_do_cpuid(struct c #else if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 ) { - if ( !v->domain->arch.hvm_domain.pae_enabled ) + if ( v->domain->arch.hvm_domain.pae_enabled ) + clear_bit(X86_FEATURE_PSE36, &edx); + else + { clear_bit(X86_FEATURE_PAE, &edx); - clear_bit(X86_FEATURE_PSE, &edx); - clear_bit(X86_FEATURE_PSE36, &edx); + clear_bit(X86_FEATURE_PSE, &edx); + clear_bit(X86_FEATURE_PSE36, &edx); + } } #endif @@ -2053,8 +2093,26 @@ asmlinkage void vmx_vmexit_handler(struc if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) { - printk("Failed vm entry (reason 0x%x)\n", exit_reason); - printk("*********** VMCS Area **************\n"); + unsigned int failed_vmentry_reason = exit_reason & 0xFFFF; + + __vmread(EXIT_QUALIFICATION, &exit_qualification); + printk("Failed vm entry (exit reason 0x%x) ", exit_reason); + switch ( failed_vmentry_reason ) { + case EXIT_REASON_INVALID_GUEST_STATE: + printk("caused by invalid guest state (%ld).\n", exit_qualification); + break; + case EXIT_REASON_MSR_LOADING: + printk("caused by MSR entry %ld loading.\n", exit_qualification); + break; + case EXIT_REASON_MACHINE_CHECK: + printk("caused by machine check.\n"); + break; + default: + printk("reason not known yet!"); + break; + } + + printk("************* VMCS Area **************\n"); vmcs_dump_vcpu(); printk("**************************************\n"); domain_crash_synchronous(); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/setup.c Wed Jul 05 20:11:37 2006 -0600 @@ -439,8 +439,9 @@ void __init __start_xen(multiboot_info_t scheduler_init(); - idle_domain = domain_create(IDLE_DOMAIN_ID, 0); - BUG_ON(idle_domain == NULL); + idle_domain = domain_create(IDLE_DOMAIN_ID); + if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) ) + BUG(); set_current(idle_domain->vcpu[0]); this_cpu(curr_vcpu) = idle_domain->vcpu[0]; @@ -537,8 +538,8 @@ void __init __start_xen(multiboot_info_t acm_init(&initrdidx, mbi, initial_images_start); /* Create initial domain 0. */ - dom0 = domain_create(0, 0); - if ( dom0 == NULL ) + dom0 = domain_create(0); + if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) ) panic("Error creating domain 0\n"); set_bit(_DOMF_privileged, &dom0->domain_flags); @@ -624,7 +625,7 @@ void arch_get_xen_caps(xen_capabilities_ if ( hvm_enabled ) { p += sprintf(p, "hvm-%d.%d-x86_32 ", XEN_VERSION, XEN_SUBVERSION); - //p += sprintf(p, "hvm-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION); + p += sprintf(p, "hvm-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION); } #elif defined(CONFIG_X86_64) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/shadow.c Wed Jul 05 20:11:37 2006 -0600 @@ -1726,6 +1726,7 @@ static int resync_all(struct domain *d, { guest_l1_pgentry_t tmp_gl1e = guest_l1e_empty(); validate_pte_change(d, tmp_gl1e, sl1e_p); + unshadow_l1 = 1; continue; } #endif @@ -3676,20 +3677,19 @@ static inline int l2e_rw_fault( put_page_from_l1e(old_sl1e, d); } - l1_p[gpfn - start_gpfn] = sl1e; - if (rw) { /* shadow_mark_va_out_of_sync() need modificatin for 2M pages*/ if ( mfn_is_page_table(mfn) ) shadow_mark_va_out_of_sync_2mp(v, gpfn, mfn, l2e_get_paddr(sl2e) | (sizeof(l1_pgentry_t) * (gpfn - start_gpfn))); } + + l1_p[gpfn - start_gpfn] = sl1e; } unmap_domain_page(l1_p); *gl2e_p = gl2e; return 1; - } /* @@ -3724,7 +3724,13 @@ static inline int guest_page_fault( } if ( guest_l2e_get_flags(*gpl2e) & _PAGE_PSE ) + { + printk("None-PAE HVM guests can NOT use PSE, " + "because we don't support 4MBytes PSE pages.\n"); + printk("remove pae=1 from your config file.\n"); + domain_crash_synchronous(); return 0; + } __guest_get_l1e(v, va, gpl1e); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/smpboot.c --- a/xen/arch/x86/smpboot.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/smpboot.c Wed Jul 05 20:11:37 2006 -0600 @@ -1197,8 +1197,7 @@ int __devinit __cpu_up(unsigned int cpu) cpu_set(cpu, smp_commenced_mask); while (!cpu_isset(cpu, cpu_online_map)) { mb(); - if (softirq_pending(0)) - do_softirq(); + process_pending_timers(); } return 0; } diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/traps.c Wed Jul 05 20:11:37 2006 -0600 @@ -426,10 +426,32 @@ DO_ERROR(17, "alignment check", alignmen DO_ERROR(17, "alignment check", alignment_check) DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error) +int cpuid_hypervisor_leaves( + uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) +{ + if ( (idx < 0x40000000) || (idx > 0x40000000) ) + return 0; + + switch ( idx - 0x40000000 ) + { + case 0: + *eax = 0x40000000; + *ebx = 0x006e6558; /* "Xen\0" */ + *ecx = *edx = 0; + break; + + default: + BUG(); + } + + return 1; +} + static int emulate_forced_invalid_op(struct cpu_user_regs *regs) { char signature[5], instr[2]; - unsigned long a, b, c, d, eip; + uint32_t a, b, c, d; + unsigned long eip; a = regs->eax; b = regs->ebx; @@ -465,6 +487,10 @@ static int emulate_forced_invalid_op(str clear_bit(X86_FEATURE_SEP, &d); if ( !IS_PRIV(current->domain) ) clear_bit(X86_FEATURE_MTRR, &d); + } + else + { + (void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d); } regs->eax = a; @@ -1397,13 +1423,14 @@ static void nmi_dom0_report(unsigned int static void nmi_dom0_report(unsigned int reason_idx) { struct domain *d; - - if ( (d = dom0) == NULL ) + struct vcpu *v; + + if ( ((d = dom0) == NULL) || ((v = d->vcpu[0]) == NULL) ) return; set_bit(reason_idx, &d->shared_info->arch.nmi_reason); - if ( test_and_set_bit(_VCPUF_nmi_pending, &d->vcpu[0]->vcpu_flags) ) + if ( test_and_set_bit(_VCPUF_nmi_pending, &v->vcpu_flags) ) raise_softirq(NMI_SOFTIRQ); /* not safe to wake up a vcpu here */ } diff -r 26dae1c72cd9 -r 2b815d9acdea xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/arch/x86/x86_emulate.c Wed Jul 05 20:11:37 2006 -0600 @@ -118,7 +118,7 @@ static uint8_t opcode_table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 - 0xC7 */ ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0, - 0, 0, ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM, + 0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, /* 0xC8 - 0xCF */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 - 0xD7 */ diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/dom0_ops.c Wed Jul 05 20:11:37 2006 -0600 @@ -90,6 +90,44 @@ static void getdomaininfo(struct domain memcpy(info->handle, d->handle, sizeof(xen_domain_handle_t)); } +static unsigned int default_vcpu0_location(void) +{ + struct domain *d; + struct vcpu *v; + unsigned int i, cpu, cnt[NR_CPUS] = { 0 }; + cpumask_t cpu_exclude_map; + + /* Do an initial CPU placement. Pick the least-populated CPU. */ + read_lock(&domlist_lock); + for_each_domain ( d ) + for_each_vcpu ( d, v ) + if ( !test_bit(_VCPUF_down, &v->vcpu_flags) ) + cnt[v->processor]++; + read_unlock(&domlist_lock); + + /* + * If we're on a HT system, we only auto-allocate to a non-primary HT. We + * favour high numbered CPUs in the event of a tie. + */ + cpu = first_cpu(cpu_sibling_map[0]); + if ( cpus_weight(cpu_sibling_map[0]) > 1 ) + cpu = next_cpu(cpu, cpu_sibling_map[0]); + cpu_exclude_map = cpu_sibling_map[0]; + for_each_online_cpu ( i ) + { + if ( cpu_isset(i, cpu_exclude_map) ) + continue; + if ( (i == first_cpu(cpu_sibling_map[i])) && + (cpus_weight(cpu_sibling_map[i]) > 1) ) + continue; + cpus_or(cpu_exclude_map, cpu_exclude_map, cpu_sibling_map[i]); + if ( cnt[i] <= cnt[cpu] ) + cpu = i; + } + + return cpu; +} + long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op) { long ret = 0; @@ -150,7 +188,7 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op if ( d != NULL ) { ret = -EINVAL; - if ( (d != current->domain) && + if ( (d != current->domain) && (d->vcpu[0] != NULL) && test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) ) { domain_unpause_by_systemcontroller(d); @@ -164,11 +202,7 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op case DOM0_CREATEDOMAIN: { struct domain *d; - unsigned int pro; domid_t dom; - struct vcpu *v; - unsigned int i, cnt[NR_CPUS] = { 0 }; - cpumask_t cpu_exclude_map; static domid_t rover = 0; /* @@ -202,36 +236,8 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op rover = dom; } - /* Do an initial CPU placement. Pick the least-populated CPU. */ - read_lock(&domlist_lock); - for_each_domain ( d ) - for_each_vcpu ( d, v ) - if ( !test_bit(_VCPUF_down, &v->vcpu_flags) ) - cnt[v->processor]++; - read_unlock(&domlist_lock); - - /* - * If we're on a HT system, we only auto-allocate to a non-primary HT. - * We favour high numbered CPUs in the event of a tie. - */ - pro = first_cpu(cpu_sibling_map[0]); - if ( cpus_weight(cpu_sibling_map[0]) > 1 ) - pro = next_cpu(pro, cpu_sibling_map[0]); - cpu_exclude_map = cpu_sibling_map[0]; - for_each_online_cpu ( i ) - { - if ( cpu_isset(i, cpu_exclude_map) ) - continue; - if ( (i == first_cpu(cpu_sibling_map[i])) && - (cpus_weight(cpu_sibling_map[i]) > 1) ) - continue; - cpus_or(cpu_exclude_map, cpu_exclude_map, cpu_sibling_map[i]); - if ( cnt[i] <= cnt[pro] ) - pro = i; - } - ret = -ENOMEM; - if ( (d = domain_create(dom, pro)) == NULL ) + if ( (d = domain_create(dom)) == NULL ) break; memcpy(d->handle, op->u.createdomain.handle, @@ -258,14 +264,8 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op if ( (d = find_domain_by_id(op->u.max_vcpus.domain)) == NULL ) break; - /* - * Can only create new VCPUs while the domain is not fully constructed - * (and hence not runnable). Xen needs auditing for races before - * removing this check. - */ - ret = -EINVAL; - if ( test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) ) - goto maxvcpu_out; + /* Needed, for example, to ensure writable p.t. state is synced. */ + domain_pause(d); /* We cannot reduce maximum VCPUs. */ ret = -EINVAL; @@ -275,17 +275,21 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op ret = -ENOMEM; for ( i = 0; i < max; i++ ) { - if ( d->vcpu[i] == NULL ) - { - cpu = (d->vcpu[i-1]->processor + 1) % num_online_cpus(); - if ( alloc_vcpu(d, i, cpu) == NULL ) - goto maxvcpu_out; - } + if ( d->vcpu[i] != NULL ) + continue; + + cpu = (i == 0) ? + default_vcpu0_location() : + (d->vcpu[i-1]->processor + 1) % num_online_cpus(); + + if ( alloc_vcpu(d, i, cpu) == NULL ) + goto maxvcpu_out; } ret = 0; maxvcpu_out: + domain_unpause(d); put_domain(d); } break; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/domain.c --- a/xen/common/domain.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/domain.c Wed Jul 05 20:11:37 2006 -0600 @@ -46,6 +46,7 @@ struct domain *alloc_domain(domid_t domi atomic_set(&d->refcnt, 1); spin_lock_init(&d->big_lock); spin_lock_init(&d->page_alloc_lock); + spin_lock_init(&d->pause_lock); INIT_LIST_HEAD(&d->page_list); INIT_LIST_HEAD(&d->xenpage_list); @@ -81,8 +82,8 @@ struct vcpu *alloc_vcpu( v->domain = d; v->vcpu_id = vcpu_id; v->processor = cpu_id; - atomic_set(&v->pausecnt, 0); v->vcpu_info = &d->shared_info->vcpu_info[vcpu_id]; + spin_lock_init(&v->pause_lock); v->cpu_affinity = is_idle_domain(d) ? cpumask_of_cpu(cpu_id) : CPU_MASK_ALL; @@ -110,30 +111,22 @@ struct vcpu *alloc_idle_vcpu(unsigned in { struct domain *d; struct vcpu *v; - unsigned int vcpu_id; - - if ((vcpu_id = cpu_id % MAX_VIRT_CPUS) == 0) - { - d = domain_create(IDLE_DOMAIN_ID, cpu_id); - BUG_ON(d == NULL); - v = d->vcpu[0]; - } - else - { - d = idle_vcpu[cpu_id - vcpu_id]->domain; - BUG_ON(d == NULL); - v = alloc_vcpu(d, vcpu_id, cpu_id); - } - + unsigned int vcpu_id = cpu_id % MAX_VIRT_CPUS; + + d = (vcpu_id == 0) ? + domain_create(IDLE_DOMAIN_ID) : + idle_vcpu[cpu_id - vcpu_id]->domain; + BUG_ON(d == NULL); + + v = alloc_vcpu(d, vcpu_id, cpu_id); idle_vcpu[cpu_id] = v; return v; } -struct domain *domain_create(domid_t domid, unsigned int cpu) +struct domain *domain_create(domid_t domid) { struct domain *d, **pd; - struct vcpu *v; if ( (d = alloc_domain(domid)) == NULL ) return NULL; @@ -152,13 +145,10 @@ struct domain *domain_create(domid_t dom if ( arch_domain_create(d) != 0 ) goto fail3; - if ( (v = alloc_vcpu(d, 0, cpu)) == NULL ) - goto fail4; - d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); d->irq_caps = rangeset_new(d, "Interrupts", 0); if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) ) - goto fail4; /* NB. alloc_vcpu() is undone in free_domain() */ + goto fail4; if ( !is_idle_domain(d) ) { @@ -327,11 +317,12 @@ void domain_shutdown(struct domain *d, u d->shutdown_code = reason; /* Put every vcpu to sleep, but don't wait (avoids inter-vcpu deadlock). */ + spin_lock(&d->pause_lock); + d->pause_count++; + set_bit(_DOMF_paused, &d->domain_flags); + spin_unlock(&d->pause_lock); for_each_vcpu ( d, v ) - { - atomic_inc(&v->pausecnt); vcpu_sleep_nosync(v); - } get_knownalive_domain(d); domain_shuttingdown[smp_processor_id()] = d; @@ -398,34 +389,65 @@ void domain_destroy(struct domain *d) void vcpu_pause(struct vcpu *v) { - BUG_ON(v == current); - atomic_inc(&v->pausecnt); + ASSERT(v != current); + + spin_lock(&v->pause_lock); + if ( v->pause_count++ == 0 ) + set_bit(_VCPUF_paused, &v->vcpu_flags); + spin_unlock(&v->pause_lock); + vcpu_sleep_sync(v); } +void vcpu_unpause(struct vcpu *v) +{ + int wake; + + ASSERT(v != current); + + spin_lock(&v->pause_lock); + wake = (--v->pause_count == 0); + if ( wake ) + clear_bit(_VCPUF_paused, &v->vcpu_flags); + spin_unlock(&v->pause_lock); + + if ( wake ) + vcpu_wake(v); +} + void domain_pause(struct domain *d) { struct vcpu *v; + ASSERT(d != current->domain); + + spin_lock(&d->pause_lock); + if ( d->pause_count++ == 0 ) + set_bit(_DOMF_paused, &d->domain_flags); + spin_unlock(&d->pause_lock); + for_each_vcpu( d, v ) - vcpu_pause(v); + vcpu_sleep_sync(v); sync_pagetable_state(d); } -void vcpu_unpause(struct vcpu *v) -{ - BUG_ON(v == current); - if ( atomic_dec_and_test(&v->pausecnt) ) - vcpu_wake(v); -} - void domain_unpause(struct domain *d) { struct vcpu *v; - - for_each_vcpu( d, v ) - vcpu_unpause(v); + int wake; + + ASSERT(d != current->domain); + + spin_lock(&d->pause_lock); + wake = (--d->pause_count == 0); + if ( wake ) + clear_bit(_DOMF_paused, &d->domain_flags); + spin_unlock(&d->pause_lock); + + if ( wake ) + for_each_vcpu( d, v ) + vcpu_wake(v); } void domain_pause_by_systemcontroller(struct domain *d) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/elf.c --- a/xen/common/elf.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/elf.c Wed Jul 05 20:11:37 2006 -0600 @@ -23,7 +23,7 @@ int parseelfimage(struct domain_setup_in Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr; Elf_Phdr *phdr; Elf_Shdr *shdr; - unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base, elf_pa_off; + Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_base, elf_pa_off; char *shstrtab, *guestinfo=NULL, *p; char *elfbase = (char *)dsi->image_addr; int h, virt_base_defined, elf_pa_off_defined; @@ -95,7 +95,11 @@ int parseelfimage(struct domain_setup_in elf_pa_off = elf_pa_off_defined ? simple_strtoul(p+17, &p, 0) : virt_base; if ( elf_pa_off_defined && !virt_base_defined ) - goto bad_image; + { + printk("ERROR: Neither ELF_PADDR_OFFSET nor VIRT_BASE found in" + " __xen_guest section.\n"); + return -EINVAL; + } for ( h = 0; h < ehdr->e_phnum; h++ ) { @@ -104,7 +108,11 @@ int parseelfimage(struct domain_setup_in continue; vaddr = phdr->p_paddr - elf_pa_off + virt_base; if ( (vaddr + phdr->p_memsz) < vaddr ) - goto bad_image; + { + printk("ERROR: ELF program header %d is too large.\n", h); + return -EINVAL; + } + if ( vaddr < kernstart ) kernstart = vaddr; if ( (vaddr + phdr->p_memsz) > kernend ) @@ -127,7 +135,10 @@ int parseelfimage(struct domain_setup_in (dsi->v_kernentry < kernstart) || (dsi->v_kernentry > kernend) || (dsi->v_start > kernstart) ) - goto bad_image; + { + printk("ERROR: ELF start or entries are out of bounds.\n"); + return -EINVAL; + } if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) dsi->load_symtab = 1; @@ -139,10 +150,6 @@ int parseelfimage(struct domain_setup_in loadelfsymtab(dsi, 0); return 0; - - bad_image: - printk("Malformed ELF image.\n"); - return -EINVAL; } int loadelfimage(struct domain_setup_info *dsi) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/event_channel.c --- a/xen/common/event_channel.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/event_channel.c Wed Jul 05 20:11:37 2006 -0600 @@ -525,11 +525,16 @@ void send_guest_global_virq(struct domai void send_guest_global_virq(struct domain *d, int virq) { int port; + struct vcpu *v; struct evtchn *chn; ASSERT(virq_is_global(virq)); - port = d->vcpu[0]->virq_to_evtchn[virq]; + v = d->vcpu[0]; + if ( unlikely(v == NULL) ) + return; + + port = v->virq_to_evtchn[virq]; if ( unlikely(port == 0) ) return; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/grant_table.c --- a/xen/common/grant_table.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/grant_table.c Wed Jul 05 20:11:37 2006 -0600 @@ -287,10 +287,10 @@ __gnttab_map_grant_ref( if ( !(op->flags & GNTMAP_readonly) && !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) ) - clear_bit(_GTF_writing, &sha->flags); + gnttab_clear_flag(_GTF_writing, &sha->flags); if ( !act->pin ) - clear_bit(_GTF_reading, &sha->flags); + gnttab_clear_flag(_GTF_reading, &sha->flags); unlock_out: spin_unlock(&rd->grant_table->lock); @@ -425,10 +425,10 @@ __gnttab_unmap_grant_ref( if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) && !(flags & GNTMAP_readonly) ) - clear_bit(_GTF_writing, &sha->flags); + gnttab_clear_flag(_GTF_writing, &sha->flags); if ( act->pin == 0 ) - clear_bit(_GTF_reading, &sha->flags); + gnttab_clear_flag(_GTF_reading, &sha->flags); unmap_out: op->status = rc; @@ -889,11 +889,11 @@ gnttab_release_mappings( } if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 ) - clear_bit(_GTF_writing, &sha->flags); + gnttab_clear_flag(_GTF_writing, &sha->flags); } if ( act->pin == 0 ) - clear_bit(_GTF_reading, &sha->flags); + gnttab_clear_flag(_GTF_reading, &sha->flags); spin_unlock(&rd->grant_table->lock); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/memory.c --- a/xen/common/memory.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/memory.c Wed Jul 05 20:11:37 2006 -0600 @@ -169,6 +169,15 @@ guest_remove_page( if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) put_page(page); + + if ( unlikely((page->count_info & PGC_count_mask) != 1) ) + { + /* We'll make this a guest-visible error in future, so take heed! */ + DPRINTK("Dom%d freeing in-use page %lx (pseudophys %lx):" + " count=%x type=%lx\n", + d->domain_id, mfn, get_gpfn_from_mfn(mfn), + page->count_info, page->u.inuse.type_info); + } guest_physmap_remove_page(d, gmfn, mfn); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/page_alloc.c --- a/xen/common/page_alloc.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/page_alloc.c Wed Jul 05 20:11:37 2006 -0600 @@ -388,7 +388,6 @@ void scrub_heap_pages(void) { void *p; unsigned long pfn; - int cpu = smp_processor_id(); printk("Scrubbing Free RAM: "); @@ -398,8 +397,7 @@ void scrub_heap_pages(void) if ( (pfn % ((100*1024*1024)/PAGE_SIZE)) == 0 ) printk("."); - if ( unlikely(softirq_pending(cpu)) ) - do_softirq(); + process_pending_timers(); /* Quick lock-free check. */ if ( allocated_in_map(pfn) ) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/sched_credit.c --- a/xen/common/sched_credit.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/sched_credit.c Wed Jul 05 20:11:37 2006 -0600 @@ -622,9 +622,12 @@ csched_dom_cntl( if ( cmd->u.credit.weight != 0 ) { - csched_priv.weight -= sdom->weight; + if ( !list_empty(&sdom->active_sdom_elem) ) + { + csched_priv.weight -= sdom->weight; + csched_priv.weight += cmd->u.credit.weight; + } sdom->weight = cmd->u.credit.weight; - csched_priv.weight += sdom->weight; } if ( cmd->u.credit.cap != (uint16_t)~0U ) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/sched_sedf.c --- a/xen/common/sched_sedf.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/sched_sedf.c Wed Jul 05 20:11:37 2006 -0600 @@ -1429,6 +1429,8 @@ static int sedf_adjdom(struct domain *p, } else if ( cmd->direction == SCHED_INFO_GET ) { + if ( p->vcpu[0] == NULL ) + return -EINVAL; cmd->u.sedf.period = EDOM_INFO(p->vcpu[0])->period; cmd->u.sedf.slice = EDOM_INFO(p->vcpu[0])->slice; cmd->u.sedf.extratime = EDOM_INFO(p->vcpu[0])->status & EXTRA_AWARE; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/schedule.c --- a/xen/common/schedule.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/schedule.c Wed Jul 05 20:11:37 2006 -0600 @@ -389,11 +389,32 @@ long do_set_timer_op(s_time_t timeout) long do_set_timer_op(s_time_t timeout) { struct vcpu *v = current; + s_time_t offset = timeout - NOW(); if ( timeout == 0 ) + { stop_timer(&v->timer); + } + else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */ + unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) ) + { + /* + * Linux workaround: occasionally we will see timeouts a long way in + * the future due to wrapping in Linux's jiffy time handling. We check + * for timeouts wrapped negative, and for positive timeouts more than + * about 13 days in the future (2^50ns). The correct fix is to trigger + * an interrupt immediately (since Linux in fact has pending work to + * do in this situation). + */ + DPRINTK("Warning: huge timeout set by domain %d (vcpu %d):" + " %"PRIx64"\n", + v->domain->domain_id, v->vcpu_id, (uint64_t)timeout); + send_timer_event(v); + } else + { set_timer(&v->timer, timeout); + } return 0; } diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/softirq.c --- a/xen/common/softirq.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/softirq.c Wed Jul 05 20:11:37 2006 -0600 @@ -23,17 +23,23 @@ static softirq_handler softirq_handlers[ asmlinkage void do_softirq(void) { - unsigned int i, cpu = smp_processor_id(); + unsigned int i, cpu; unsigned long pending; - pending = softirq_pending(cpu); - ASSERT(pending != 0); + for ( ; ; ) + { + /* + * Initialise @cpu on every iteration: SCHEDULE_SOFTIRQ may move + * us to another processor. + */ + cpu = smp_processor_id(); + if ( (pending = softirq_pending(cpu)) == 0 ) + break; - do { i = find_first_set_bit(pending); clear_bit(i, &softirq_pending(cpu)); (*softirq_handlers[i])(); - } while ( (pending = softirq_pending(cpu)) != 0 ); + } } void open_softirq(int nr, softirq_handler handler) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/common/timer.c --- a/xen/common/timer.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/common/timer.c Wed Jul 05 20:11:37 2006 -0600 @@ -327,6 +327,15 @@ static void timer_softirq_action(void) } +void process_pending_timers(void) +{ + unsigned int cpu = smp_processor_id(); + ASSERT(!in_irq() && local_irq_is_enabled()); + if ( test_and_clear_bit(TIMER_SOFTIRQ, &softirq_pending(cpu)) ) + timer_softirq_action(); +} + + static void dump_timerq(unsigned char key) { struct timer *t; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/drivers/char/console.c --- a/xen/drivers/char/console.c Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/drivers/char/console.c Wed Jul 05 20:11:37 2006 -0600 @@ -279,7 +279,7 @@ static void switch_serial_input(void) { static char *input_str[2] = { "DOM0", "Xen" }; xen_rx = !xen_rx; - if ( SWITCH_CODE != 0 ) + if ( (SWITCH_CODE != 0) && (dom0 != NULL) ) { printk("*** Serial input -> %s " "(type 'CTRL-%c' three times to switch input to %s).\n", @@ -528,8 +528,7 @@ void console_endboot(void) printk("%d... ", 3-i); for ( j = 0; j < 100; j++ ) { - if ( softirq_pending(smp_processor_id()) ) - do_softirq(); + process_pending_timers(); mdelay(10); } } @@ -741,6 +740,15 @@ void panic(const char *fmt, ...) machine_restart(0); } +void __bug(char *file, int line) +{ + console_start_sync(); + debugtrace_dump(); + printk("BUG at %s:%d\n", file, line); + FORCE_CRASH(); + for ( ; ; ) ; +} + /* * Local variables: * mode: C diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/asm-ia64/grant_table.h --- a/xen/include/asm-ia64/grant_table.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/asm-ia64/grant_table.h Wed Jul 05 20:11:37 2006 -0600 @@ -55,4 +55,9 @@ void guest_physmap_add_page(struct domai #define gnttab_log_dirty(d, f) ((void)0) +static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) +{ + clear_bit(nr, addr); +} + #endif /* __ASM_GRANT_TABLE_H__ */ diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/asm-x86/grant_table.h --- a/xen/include/asm-x86/grant_table.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/asm-x86/grant_table.h Wed Jul 05 20:11:37 2006 -0600 @@ -33,4 +33,9 @@ int destroy_grant_host_mapping( #define gnttab_log_dirty(d, f) mark_dirty((d), (f)) +static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) +{ + clear_bit(nr, addr); +} + #endif /* __ASM_GRANT_TABLE_H__ */ diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Jul 05 20:11:37 2006 -0600 @@ -27,9 +27,7 @@ extern int start_vmx(void); extern int start_vmx(void); extern void stop_vmx(void); extern void vmcs_dump_vcpu(void); -void vmx_final_setup_guest(struct vcpu *v); - -void vmx_enter_scheduler(void); +extern void vmx_init_vmcs_config(void); enum { VMX_CPU_STATE_PAE_ENABLED=0, @@ -45,8 +43,6 @@ struct vmcs_struct { u32 vmcs_revision_id; unsigned char data [0]; /* vmcs size is read from MSR */ }; - -extern int vmcs_size; enum { VMX_INDEX_MSR_LSTAR = 0, @@ -63,6 +59,10 @@ struct vmx_msr_state { unsigned long msr_items[VMX_MSR_COUNT]; unsigned long shadow_gs; }; + +/* io bitmap is 4KBytes in size */ +#define IO_BITMAP_SIZE 0x1000 +#define IO_BITMAP_ORDER (get_order_from_bytes(IO_BITMAP_SIZE)) struct arch_vmx_struct { /* Virtual address of VMCS. */ @@ -101,7 +101,10 @@ struct arch_vmx_struct { void vmx_do_resume(struct vcpu *); -struct vmcs_struct *vmx_alloc_vmcs(void); +struct vmcs_struct *vmx_alloc_host_vmcs(void); +void vmx_free_host_vmcs(struct vmcs_struct *vmcs); + +int vmx_create_vmcs(struct vcpu *v); void vmx_destroy_vmcs(struct vcpu *v); void vmx_vmcs_enter(struct vcpu *v); void vmx_vmcs_exit(struct vcpu *v); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Wed Jul 05 20:11:37 2006 -0600 @@ -133,6 +133,11 @@ extern unsigned int cpu_rev; #define EXIT_REASON_MSR_WRITE 32 #define EXIT_REASON_MWAIT_INSTRUCTION 36 +#define EXIT_REASON_INVALID_GUEST_STATE 33 +#define EXIT_REASON_MSR_LOADING 34 +#define EXIT_REASON_MACHINE_CHECK 41 + + /* * Interruption-information format */ diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/asm-x86/processor.h Wed Jul 05 20:11:37 2006 -0600 @@ -545,6 +545,9 @@ extern void mtrr_bp_init(void); extern void mcheck_init(struct cpuinfo_x86 *c); +int cpuid_hypervisor_leaves( + uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx); + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_X86_PROCESSOR_H */ diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/public/arch-ia64.h --- a/xen/include/public/arch-ia64.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/public/arch-ia64.h Wed Jul 05 20:11:37 2006 -0600 @@ -39,6 +39,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MAX_VIRT_CPUS 64 #ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; #define GPFN_MEM (0UL << 56) /* Guest pfn is normal mem */ #define GPFN_FRAME_BUFFER (1UL << 56) /* VGA framebuffer */ diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/public/arch-x86_32.h --- a/xen/include/public/arch-x86_32.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/public/arch-x86_32.h Wed Jul 05 20:11:37 2006 -0600 @@ -97,6 +97,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MAX_VIRT_CPUS 32 #ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; /* * Send an array of these to HYPERVISOR_set_trap_table() diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/public/arch-x86_64.h --- a/xen/include/public/arch-x86_64.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/public/arch-x86_64.h Wed Jul 05 20:11:37 2006 -0600 @@ -104,6 +104,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define MAX_VIRT_CPUS 32 #ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; /* * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base) diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/public/dom0_ops.h Wed Jul 05 20:11:37 2006 -0600 @@ -162,7 +162,7 @@ DEFINE_XEN_GUEST_HANDLE(dom0_settime_t); struct dom0_getpageframeinfo { /* IN variables. */ - xen_pfn_t mfn; /* Machine page frame number to query. */ + xen_pfn_t gmfn; /* GMFN to query. */ domid_t domain; /* To which domain does the frame belong? */ /* OUT variables. */ /* Is the page PINNED to a type? */ @@ -177,9 +177,9 @@ DEFINE_XEN_GUEST_HANDLE(dom0_getpagefram #define DOM0_READCONSOLE 19 struct dom0_readconsole { /* IN variables. */ - uint32_t clear; /* Non-zero -> clear after reading. */ + uint32_t clear; /* Non-zero -> clear after reading. */ + XEN_GUEST_HANDLE(char) buffer; /* Buffer start */ /* IN/OUT variables. */ - XEN_GUEST_HANDLE(char) buffer; /* In: Buffer start; Out: Used buffer start */ uint32_t count; /* In: Buffer size; Out: Used buffer size */ }; typedef struct dom0_readconsole dom0_readconsole_t; @@ -509,8 +509,8 @@ DEFINE_XEN_GUEST_HANDLE(dom0_iomem_permi #define DOM0_HYPERCALL_INIT 48 struct dom0_hypercall_init { - domid_t domain; /* domain to be affected */ - xen_pfn_t mfn; /* machine frame to be initialised */ + domid_t domain; /* domain to be affected */ + xen_pfn_t gmfn; /* GMFN to be initialised */ }; typedef struct dom0_hypercall_init dom0_hypercall_init_t; DEFINE_XEN_GUEST_HANDLE(dom0_hypercall_init_t); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/public/io/netif.h Wed Jul 05 20:11:37 2006 -0600 @@ -23,8 +23,9 @@ * This is the 'wire' format for packets: * Request 1: netif_tx_request -- NETTXF_* (any flags) * [Request 2: netif_tx_extra] (only if request 1 has NETTXF_extra_info) - * Request 3: netif_tx_request -- NETTXF_more_data + * [Request 3: netif_tx_extra] (only if request 2 has XEN_NETIF_EXTRA_MORE) * Request 4: netif_tx_request -- NETTXF_more_data + * Request 5: netif_tx_request -- NETTXF_more_data * ... * Request N: netif_tx_request -- 0 */ @@ -41,12 +42,9 @@ #define _NETTXF_more_data (2) #define NETTXF_more_data (1U<<_NETTXF_more_data) -/* Packet has GSO fields in the following descriptor (netif_tx_extra.u.gso). */ -#define _NETTXF_gso (3) -#define NETTXF_gso (1U<<_NETTXF_gso) - -/* This descriptor is followed by an extra-info descriptor (netif_tx_extra). */ -#define NETTXF_extra_info (NETTXF_gso) +/* Packet to be followed by extra descriptor(s). */ +#define _NETTXF_extra_info (3) +#define NETTXF_extra_info (1U<<_NETTXF_extra_info) struct netif_tx_request { grant_ref_t gref; /* Reference to buffer page */ @@ -57,15 +55,51 @@ struct netif_tx_request { }; typedef struct netif_tx_request netif_tx_request_t; -/* This structure needs to fit within netif_tx_request for compatibility. */ -struct netif_tx_extra { +/* Types of netif_extra_info descriptors. */ +#define XEN_NETIF_EXTRA_TYPE_NONE (0) /* Never used - invalid */ +#define XEN_NETIF_EXTRA_TYPE_GSO (1) /* u.gso */ +#define XEN_NETIF_EXTRA_TYPE_MAX (2) + +/* netif_extra_info flags. */ +#define _XEN_NETIF_EXTRA_FLAG_MORE (0) +#define XEN_NETIF_EXTRA_FLAG_MORE (1U<<_XEN_NETIF_EXTRA_FLAG_MORE) + +/* GSO types - only TCPv4 currently supported. */ +#define XEN_NETIF_GSO_TYPE_TCPV4 (1) + +/* + * This structure needs to fit within both netif_tx_request and + * netif_rx_response for compatibility. + */ +struct netif_extra_info { + uint8_t type; /* XEN_NETIF_EXTRA_TYPE_* */ + uint8_t flags; /* XEN_NETIF_EXTRA_FLAG_* */ + union { - /* NETTXF_gso: Generic Segmentation Offload. */ - struct netif_tx_gso { - uint16_t size; /* GSO MSS. */ - uint16_t segs; /* GSO segment count. */ - uint16_t type; /* GSO type. */ + struct { + /* + * Maximum payload size of each segment. For example, for TCP this + * is just the path MSS. + */ + uint16_t size; + + /* + * GSO type. This determines the protocol of the packet and any + * extra features required to segment the packet properly. + */ + uint8_t type; /* XEN_NETIF_GSO_TYPE_* */ + + /* Future expansion. */ + uint8_t pad; + + /* + * GSO features. This specifies any extra GSO features required + * to process this packet, such as ECN support for TCPv4. + */ + uint16_t features; /* XEN_NETIF_GSO_FEAT_* */ } gso; + + uint16_t pad[3]; } u; }; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/public/memory.h --- a/xen/include/public/memory.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/public/memory.h Wed Jul 05 20:11:37 2006 -0600 @@ -32,7 +32,7 @@ struct xen_memory_reservation { XEN_GUEST_HANDLE(xen_pfn_t) extent_start; /* Number of extents, and size/alignment of each (2^extent_order pages). */ - unsigned long nr_extents; + xen_ulong_t nr_extents; unsigned int extent_order; /* @@ -90,7 +90,7 @@ struct xen_memory_exchange { * command will be non-zero. * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER! */ - unsigned long nr_exchanged; + xen_ulong_t nr_exchanged; }; typedef struct xen_memory_exchange xen_memory_exchange_t; DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t); @@ -148,8 +148,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mfn */ #define XENMEM_machphys_mapping 12 struct xen_machphys_mapping { - unsigned long v_start, v_end; /* Start and end virtual addresses. */ - unsigned long max_mfn; /* Maximum MFN that can be looked up. */ + xen_ulong_t v_start, v_end; /* Start and end virtual addresses. */ + xen_ulong_t max_mfn; /* Maximum MFN that can be looked up. */ }; typedef struct xen_machphys_mapping xen_machphys_mapping_t; DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t); @@ -170,7 +170,7 @@ struct xen_add_to_physmap { unsigned int space; /* Index into source mapping space. */ - unsigned long idx; + xen_ulong_t idx; /* GPFN where the source mapping page should appear. */ xen_pfn_t gpfn; @@ -188,7 +188,7 @@ struct xen_translate_gpfn_list { domid_t domid; /* Length of list. */ - unsigned long nr_gpfns; + xen_ulong_t nr_gpfns; /* List of GPFNs to translate. */ XEN_GUEST_HANDLE(xen_pfn_t) gpfn_list; diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/xen/lib.h --- a/xen/include/xen/lib.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/xen/lib.h Wed Jul 05 20:11:37 2006 -0600 @@ -8,19 +8,23 @@ #include <xen/xmalloc.h> #include <xen/string.h> -#define BUG() do { \ - debugtrace_dump(); \ - printk("BUG at %s:%d\n", __FILE__, __LINE__); \ - FORCE_CRASH(); \ -} while ( 0 ) - +extern void __bug(char *file, int line) __attribute__((noreturn)); +#define BUG() __bug(__FILE__, __LINE__) #define BUG_ON(_p) do { if (_p) BUG(); } while ( 0 ) /* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)])) #ifndef NDEBUG -#define ASSERT(_p) { if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s\n", #_p , __LINE__, __FILE__); BUG(); } } +#define ASSERT(_p) \ + do { \ + if ( !(_p) ) \ + { \ + printk("Assertion '%s' failed, line %d, file %s\n", #_p , \ + __LINE__, __FILE__); \ + BUG(); \ + } \ + } while ( 0 ) #else #define ASSERT(_p) ((void)0) #endif diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/xen/sched.h --- a/xen/include/xen/sched.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/xen/sched.h Wed Jul 05 20:11:37 2006 -0600 @@ -78,9 +78,10 @@ struct vcpu unsigned long vcpu_flags; + spinlock_t pause_lock; + unsigned int pause_count; + u16 virq_to_evtchn[NR_VIRQS]; - - atomic_t pausecnt; /* Bitmask of CPUs on which this VCPU may run. */ cpumask_t cpu_affinity; @@ -141,6 +142,10 @@ struct domain struct rangeset *irq_caps; unsigned long domain_flags; + + spinlock_t pause_lock; + unsigned int pause_count; + unsigned long vm_assist; atomic_t refcnt; @@ -220,8 +225,7 @@ static inline void get_knownalive_domain ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTROYED)); } -extern struct domain *domain_create( - domid_t domid, unsigned int cpu); +extern struct domain *domain_create(domid_t domid); extern int construct_dom0( struct domain *d, unsigned long image_start, unsigned long image_len, @@ -368,6 +372,9 @@ extern struct domain *domain_list; /* VCPU is polling a set of event channels (SCHEDOP_poll). */ #define _VCPUF_polling 10 #define VCPUF_polling (1UL<<_VCPUF_polling) + /* VCPU is paused by the hypervisor? */ +#define _VCPUF_paused 11 +#define VCPUF_paused (1UL<<_VCPUF_paused) /* * Per-domain flags (domain_flags). @@ -390,12 +397,16 @@ extern struct domain *domain_list; /* Are any VCPUs polling event channels (SCHEDOP_poll)? */ #define _DOMF_polling 5 #define DOMF_polling (1UL<<_DOMF_polling) + /* Domain is paused by the hypervisor? */ +#define _DOMF_paused 6 +#define DOMF_paused (1UL<<_DOMF_paused) static inline int vcpu_runnable(struct vcpu *v) { - return ( (atomic_read(&v->pausecnt) == 0) && - !(v->vcpu_flags & (VCPUF_blocked|VCPUF_down)) && - !(v->domain->domain_flags & (DOMF_shutdown|DOMF_ctrl_pause)) ); + return ( !(v->vcpu_flags & + (VCPUF_blocked|VCPUF_down|VCPUF_paused)) && + !(v->domain->domain_flags & + (DOMF_shutdown|DOMF_ctrl_pause|DOMF_paused)) ); } void vcpu_pause(struct vcpu *v); diff -r 26dae1c72cd9 -r 2b815d9acdea xen/include/xen/timer.h --- a/xen/include/xen/timer.h Wed Jul 05 10:23:54 2006 -0600 +++ b/xen/include/xen/timer.h Wed Jul 05 20:11:37 2006 -0600 @@ -89,6 +89,12 @@ extern void kill_timer(struct timer *tim extern void kill_timer(struct timer *timer); /* + * Process pending timers on this CPU. This should be called periodically + * when performing work that prevents softirqs from running in a timely manner. + */ +extern void process_pending_timers(void); + +/* * Bootstrap initialisation. Must be called before any other timer function. */ extern void timer_init(void); diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/gnttab.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/gnttab.c Wed Jul 05 20:11:37 2006 -0600 @@ -0,0 +1,158 @@ +/* + **************************************************************************** + * (C) 2006 - Cambridge University + **************************************************************************** + * + * File: gnttab.c + * Author: Steven Smith (sos22@xxxxxxxxx) + * Changes: Grzegorz Milos (gm281@xxxxxxxxx) + * + * Date: July 2006 + * + * Environment: Xen Minimal OS + * Description: Simple grant tables implementation. About as stupid as it's + * possible to be and still work. + * + **************************************************************************** + */ +#include <os.h> +#include <mm.h> +#include <gnttab.h> + +#define NR_RESERVED_ENTRIES 8 + +#define NR_GRANT_FRAMES 4 +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) +#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1) + +static grant_entry_t *gnttab_table; +static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; +static grant_ref_t gnttab_free_head; + +static grant_ref_t +get_free_entries(int count) +{ + grant_ref_t ref; + grant_ref_t head; + + ref = head = gnttab_free_head; + while (count-- > 1) + head = gnttab_list[head]; + gnttab_free_head = gnttab_list[head]; + gnttab_list[head] = GNTTAB_LIST_END; + return ref; +} + +static void +put_free_entry(grant_ref_t gref) +{ + gnttab_list[gref] = gnttab_free_head; + gnttab_free_head = gref; +} + +grant_ref_t +gnttab_grant_access(domid_t domid, unsigned long frame, int readonly) +{ + grant_ref_t ref; + + ref = get_free_entries(1); + gnttab_table[ref].frame = frame; + gnttab_table[ref].domid = domid; + wmb(); + readonly *= GTF_readonly; + gnttab_table[ref].flags = GTF_permit_access | readonly; + + return ref; +} + +grant_ref_t +gnttab_grant_transfer(domid_t domid, unsigned long pfn) +{ + grant_ref_t ref; + + ref = get_free_entries(1); + gnttab_table[ref].frame = pfn; + gnttab_table[ref].domid = domid; + wmb(); + gnttab_table[ref].flags = GTF_accept_transfer; + + return ref; +} + +int +gnttab_end_access(grant_ref_t ref) +{ + u16 flags, nflags; + + nflags = gnttab_table[ref].flags; + do { + if ((flags = nflags) & (GTF_reading|GTF_writing)) { + printk("WARNING: g.e. still in use!\n"); + return 0; + } + } while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) != + flags); + + put_free_entry(ref); + return 1; +} + +unsigned long +gnttab_end_transfer(grant_ref_t ref) +{ + unsigned long frame; + u16 flags; + + while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) { + if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) { + printk("Release unused transfer grant.\n"); + put_free_entry(ref); + return 0; + } + } + + /* If a transfer is in progress then wait until it is completed. */ + while (!(flags & GTF_transfer_completed)) { + flags = gnttab_table[ref].flags; + } + + /* Read the frame number /after/ reading completion status. */ + rmb(); + frame = gnttab_table[ref].frame; + + put_free_entry(ref); + + return frame; +} + +grant_ref_t +gnttab_alloc_and_grant(void **map) +{ + unsigned long mfn; + grant_ref_t gref; + + *map = (void *)alloc_page(); + mfn = virt_to_mfn(*map); + gref = gnttab_grant_access(0, mfn, 0); + return gref; +} + +void +init_gnttab(void) +{ + struct gnttab_setup_table setup; + unsigned long frames[NR_GRANT_FRAMES]; + int i; + + for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++) + gnttab_list[i] = i + 1; + gnttab_free_head = NR_RESERVED_ENTRIES; + + setup.dom = DOMID_SELF; + setup.nr_frames = NR_GRANT_FRAMES; + set_xen_guest_handle(setup.frame_list, frames); + + HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1); + gnttab_table = map_frames(frames, NR_GRANT_FRAMES); + printk("gnttab_table mapped at %p.\n", gnttab_table); +} diff -r 26dae1c72cd9 -r 2b815d9acdea extras/mini-os/include/gnttab.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/gnttab.h Wed Jul 05 20:11:37 2006 -0600 @@ -0,0 +1,14 @@ +#ifndef __GNTTAB_H__ +#define __GNTTAB_H__ + +#include <xen/grant_table.h> + +void init_gnttab(void); +grant_ref_t gnttab_alloc_and_grant(void **map); +grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame, + int readonly); +grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn); +unsigned long gnttab_end_transfer(grant_ref_t gref); +int gnttab_end_access(grant_ref_t ref); + +#endif /* !__GNTTAB_H__ */ diff -r 26dae1c72cd9 -r 2b815d9acdea patches/linux-2.6.16.13/fix-hz-suspend.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16.13/fix-hz-suspend.patch Wed Jul 05 20:11:37 2006 -0600 @@ -0,0 +1,26 @@ +diff -pruN ../pristine-linux-2.6.16.13/kernel/timer.c ./kernel/timer.c +--- ../pristine-linux-2.6.16.13/kernel/timer.c 2006-05-02 22:38:44.000000000 +0100 ++++ ./kernel/timer.c 2006-06-29 14:34:12.788957720 +0100 +@@ -555,6 +555,22 @@ found: + } + spin_unlock(&base->t_base.lock); + ++ /* ++ * It can happen that other CPUs service timer IRQs and increment ++ * jiffies, but we have not yet got a local timer tick to process ++ * the timer wheels. In that case, the expiry time can be before ++ * jiffies, but since the high-resolution timer here is relative to ++ * jiffies, the default expression when high-resolution timers are ++ * not active, ++ * ++ * time_before(MAX_JIFFY_OFFSET + jiffies, expires) ++ * ++ * would falsely evaluate to true. If that is the case, just ++ * return jiffies so that we can immediately fire the local timer ++ */ ++ if (time_before(expires, jiffies)) ++ return jiffies; ++ + if (time_before(hr_expires, expires)) + return hr_expires; + diff -r 26dae1c72cd9 -r 2b815d9acdea patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch Wed Jul 05 20:11:37 2006 -0600 @@ -0,0 +1,1546 @@ +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c ./drivers/char/tpm/tpm_atmel.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_atmel.c 2006-06-26 18:16:33.000000000 -0400 +@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip + return -EIO; + + for (i = 0; i < 6; i++) { +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { + dev_err(chip->dev, "error reading header\n"); + return -EIO; + } +- *buf++ = ioread8(chip->vendor->iobase); ++ *buf++ = ioread8(chip->vendor.iobase); + } + + /* size of the data received */ +@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip + dev_err(chip->dev, + "Recv size(%d) less than available space\n", size); + for (; i < size; i++) { /* clear the waiting data anyway */ +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { + dev_err(chip->dev, "error reading data\n"); + return -EIO; +@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip + + /* read all the data available */ + for (; i < size; i++) { +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + if ((status & ATML_STATUS_DATA_AVAIL) == 0) { + dev_err(chip->dev, "error reading data\n"); + return -EIO; + } +- *buf++ = ioread8(chip->vendor->iobase); ++ *buf++ = ioread8(chip->vendor.iobase); + } + + /* make sure data available is gone */ +- status = ioread8(chip->vendor->iobase + 1); ++ status = ioread8(chip->vendor.iobase + 1); + + if (status & ATML_STATUS_DATA_AVAIL) { + dev_err(chip->dev, "data available is stuck\n"); +@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip + dev_dbg(chip->dev, "tpm_atml_send:\n"); + for (i = 0; i < count; i++) { + dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); +- iowrite8(buf[i], chip->vendor->iobase); ++ iowrite8(buf[i], chip->vendor.iobase); + } + + return count; +@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip + + static void tpm_atml_cancel(struct tpm_chip *chip) + { +- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1); ++ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1); + } + + static u8 tpm_atml_status(struct tpm_chip *chip) + { +- return ioread8(chip->vendor->iobase + 1); ++ return ioread8(chip->vendor.iobase + 1); + } + + static struct file_operations atmel_ops = { +@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] = + + static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; + +-static struct tpm_vendor_specific tpm_atmel = { ++static const struct tpm_vendor_specific tpm_atmel = { + .recv = tpm_atml_recv, + .send = tpm_atml_send, + .cancel = tpm_atml_cancel, +@@ -159,10 +159,10 @@ static void atml_plat_remove(void) + struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); + + if (chip) { +- if (chip->vendor->have_region) +- atmel_release_region(chip->vendor->base, +- chip->vendor->region_size); +- atmel_put_base_addr(chip->vendor); ++ if (chip->vendor.have_region) ++ atmel_release_region(chip->vendor.base, ++ chip->vendor.region_size); ++ atmel_put_base_addr(chip->vendor.iobase); + tpm_remove_hardware(chip->dev); + platform_device_unregister(pdev); + } +@@ -179,18 +179,22 @@ static struct device_driver atml_drv = { + static int __init init_atmel(void) + { + int rc = 0; ++ void __iomem *iobase = NULL; ++ int have_region, region_size; ++ unsigned long base; ++ struct tpm_chip *chip; + + driver_register(&atml_drv); + +- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) { ++ if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) { + rc = -ENODEV; + goto err_unreg_drv; + } + +- tpm_atmel.have_region = ++ have_region = + (atmel_request_region +- (tpm_atmel.base, tpm_atmel.region_size, +- "tpm_atmel0") == NULL) ? 0 : 1; ++ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1; ++ + + if (IS_ERR + (pdev = +@@ -199,17 +203,25 @@ static int __init init_atmel(void) + goto err_rel_reg; + } + +- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0) ++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { ++ rc = -ENODEV; + goto err_unreg_dev; ++ } ++ ++ chip->vendor.iobase = iobase; ++ chip->vendor.base = base; ++ chip->vendor.have_region = have_region; ++ chip->vendor.region_size = region_size; ++ + return 0; + + err_unreg_dev: + platform_device_unregister(pdev); + err_rel_reg: +- atmel_put_base_addr(&tpm_atmel); +- if (tpm_atmel.have_region) +- atmel_release_region(tpm_atmel.base, +- tpm_atmel.region_size); ++ atmel_put_base_addr(iobase); ++ if (have_region) ++ atmel_release_region(base, ++ region_size); + err_unreg_drv: + driver_unregister(&atml_drv); + return rc; +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h ./drivers/char/tpm/tpm_atmel.h +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_atmel.h 2006-06-26 18:16:33.000000000 -0400 +@@ -28,13 +28,12 @@ + #define atmel_request_region request_mem_region + #define atmel_release_region release_mem_region + +-static inline void atmel_put_base_addr(struct tpm_vendor_specific +- *vendor) ++static inline void atmel_put_base_addr(void __iomem *iobase) + { +- iounmap(vendor->iobase); ++ iounmap(iobase); + } + +-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor) ++static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) + { + struct device_node *dn; + unsigned long address, size; +@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add + else + size = reg[naddrc]; + +- vendor->base = address; +- vendor->region_size = size; +- return ioremap(vendor->base, vendor->region_size); ++ *base = address; ++ *region_size = size; ++ return ioremap(*base, *region_size); + } + #else + #define atmel_getb(chip, offset) inb(chip->vendor->base + offset) +@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void) + return 0; + } + +-static inline void atmel_put_base_addr(struct tpm_vendor_specific +- *vendor) ++static inline void atmel_put_base_addr(void __iomem *iobase) + { + } + + /* Determine where to talk to device */ +-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific +- *vendor) ++static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) + { + int lo, hi; + +@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add + lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO); + hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI); + +- vendor->base = (hi << 8) | lo; +- vendor->region_size = 2; ++ *base = (hi << 8) | lo; ++ *region_size = 2; + +- return ioport_map(vendor->base, vendor->region_size); ++ return ioport_map(*base, *region_size); + } + #endif +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c ./drivers/char/tpm/tpm_bios.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_bios.c 2006-06-26 18:16:33.000000000 -0400 +@@ -29,6 +29,11 @@ + #define MAX_TEXT_EVENT 1000 /* Max event string length */ + #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ + ++enum bios_platform_class { ++ BIOS_CLIENT = 0x00, ++ BIOS_SERVER = 0x01, ++}; ++ + struct tpm_bios_log { + void *bios_event_log; + void *bios_event_log_end; +@@ -36,9 +41,18 @@ struct tpm_bios_log { + + struct acpi_tcpa { + struct acpi_table_header hdr; +- u16 reserved; +- u32 log_max_len __attribute__ ((packed)); +- u32 log_start_addr __attribute__ ((packed)); ++ u16 platform_class; ++ union { ++ struct client_hdr { ++ u32 log_max_len __attribute__ ((packed)); ++ u64 log_start_addr __attribute__ ((packed)); ++ } client; ++ struct server_hdr { ++ u16 reserved; ++ u64 log_max_len __attribute__ ((packed)); ++ u64 log_start_addr __attribute__ ((packed)); ++ } server; ++ }; + }; + + struct tcpa_event { +@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin + "Non-Host Info" + }; + ++struct tcpa_pc_event { ++ u32 event_id; ++ u32 event_size; ++ u8 event_data[0]; ++}; ++ + enum tcpa_pc_event_ids { + SMBIOS = 1, + BIS_CERT, +@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids { + NVRAM, + OPTION_ROM_EXEC, + OPTION_ROM_CONFIG, +- OPTION_ROM_MICROCODE, ++ OPTION_ROM_MICROCODE = 10, + S_CRTM_VERSION, + S_CRTM_CONTENTS, + POST_CONTENTS, ++ HOST_TABLE_OF_DEVICES, + }; + + static const char* tcpa_pc_event_id_strings[] = { +- "" ++ "", + "SMBIOS", + "BIS Certificate", + "POST BIOS ", +@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri + "NVRAM", + "Option ROM", + "Option ROM config", +- "Option ROM microcode", ++ "", ++ "Option ROM microcode ", + "S-CRTM Version", +- "S-CRTM Contents", +- "S-CRTM POST Contents", ++ "S-CRTM Contents ", ++ "POST Contents ", ++ "Table of Devices", + }; + + /* returns pointer to start of pos. entry of tcg log */ +@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st + const char *name = ""; + char data[40] = ""; + int i, n_len = 0, d_len = 0; +- u32 event_id; ++ struct tcpa_pc_event *pc_event; + + switch(event->event_type) { + case PREBOOT: +@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st + } + break; + case EVENT_TAG: +- event_id = be32_to_cpu(*((u32 *)event_entry)); ++ pc_event = (struct tcpa_pc_event *)event_entry; + + /* ToDo Row data -> Base64 */ + +- switch (event_id) { ++ switch (pc_event->event_id) { + case SMBIOS: + case BIS_CERT: + case CMOS: + case NVRAM: + case OPTION_ROM_EXEC: + case OPTION_ROM_CONFIG: +- case OPTION_ROM_MICROCODE: + case S_CRTM_VERSION: +- case S_CRTM_CONTENTS: +- case POST_CONTENTS: +- name = tcpa_pc_event_id_strings[event_id]; ++ name = tcpa_pc_event_id_strings[pc_event->event_id]; + n_len = strlen(name); + break; ++ /* hash data */ + case POST_BIOS_ROM: + case ESCD: +- name = tcpa_pc_event_id_strings[event_id]; ++ case OPTION_ROM_MICROCODE: ++ case S_CRTM_CONTENTS: ++ case POST_CONTENTS: ++ name = tcpa_pc_event_id_strings[pc_event->event_id]; + n_len = strlen(name); + for (i = 0; i < 20; i++) +- d_len += sprintf(data, "%02x", +- event_entry[8 + i]); ++ d_len += sprintf(&data[2*i], "%02x", ++ pc_event->event_data[i]); + break; + default: + break; +@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st + + static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) + { ++ struct tcpa_event *event = v; ++ char *data = v; ++ int i; + +- char *eventname; +- char data[4]; +- u32 help; +- int i, len; +- struct tcpa_event *event = (struct tcpa_event *) v; +- unsigned char *event_entry = +- (unsigned char *) (v + sizeof(struct tcpa_event)); +- +- eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); +- if (!eventname) { +- printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", +- __func__); +- return -ENOMEM; +- } +- +- /* 1st: PCR used is in little-endian format (4 bytes) */ +- help = le32_to_cpu(event->pcr_index); +- memcpy(data, &help, 4); +- for (i = 0; i < 4; i++) +- seq_putc(m, data[i]); +- +- /* 2nd: SHA1 (20 bytes) */ +- for (i = 0; i < 20; i++) +- seq_putc(m, event->pcr_value[i]); +- +- /* 3rd: event type identifier (4 bytes) */ +- help = le32_to_cpu(event->event_type); +- memcpy(data, &help, 4); +- for (i = 0; i < 4; i++) ++ for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) + seq_putc(m, data[i]); + +- len = 0; +- +- len += get_event_name(eventname, event, event_entry); +- +- /* 4th: filename <= 255 + \'0' delimiter */ +- if (len > TCG_EVENT_NAME_LEN_MAX) +- len = TCG_EVENT_NAME_LEN_MAX; +- +- for (i = 0; i < len; i++) +- seq_putc(m, eventname[i]); +- +- /* 5th: delimiter */ +- seq_putc(m, '\0'); +- + return 0; + } + +@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s + /* 4th: eventname <= max + \'0' delimiter */ + seq_printf(m, " %s\n", eventname); + ++ kfree(eventname); + return 0; + } + +@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log + struct acpi_tcpa *buff; + acpi_status status; + struct acpi_table_header *virt; ++ u64 len, start; + + if (log->bios_event_log != NULL) { + printk(KERN_ERR +@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log + return -EIO; + } + +- if (buff->log_max_len == 0) { ++ switch(buff->platform_class) { ++ case BIOS_SERVER: ++ len = buff->server.log_max_len; ++ start = buff->server.log_start_addr; ++ break; ++ case BIOS_CLIENT: ++ default: ++ len = buff->client.log_max_len; ++ start = buff->client.log_start_addr; ++ break; ++ } ++ if (!len) { + printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); + return -EIO; + } + + /* malloc EventLog space */ +- log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); ++ log->bios_event_log = kmalloc(len, GFP_KERNEL); + if (!log->bios_event_log) { +- printk +- ("%s: ERROR - Not enough Memory for BIOS measurements\n", +- __func__); ++ printk("%s: ERROR - Not enough Memory for BIOS measurements\n", ++ __func__); + return -ENOMEM; + } + +- log->bios_event_log_end = log->bios_event_log + buff->log_max_len; ++ log->bios_event_log_end = log->bios_event_log + len; + +- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt); ++ acpi_os_map_memory(start, len, (void *) &virt); + +- memcpy(log->bios_event_log, virt, buff->log_max_len); ++ memcpy(log->bios_event_log, virt, len); + +- acpi_os_unmap_memory(virt, buff->log_max_len); ++ acpi_os_unmap_memory(virt, len); + return 0; + } + +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c ./drivers/char/tpm/tpm_infineon.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_infineon.c 2006-06-26 18:16:33.000000000 -0400 +@@ -15,6 +15,7 @@ + * License. + */ + ++#include <linux/init.h> + #include <linux/pnp.h> + #include "tpm.h" + +@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c + + if (clear_wrfifo) { + for (i = 0; i < 4096; i++) { +- status = inb(chip->vendor->base + WRFIFO); ++ status = inb(chip->vendor.base + WRFIFO); + if (status == 0xff) { + if (check == 5) + break; +@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c + */ + i = 0; + do { +- status = inb(chip->vendor->base + RDFIFO); +- status = inb(chip->vendor->base + STAT); ++ status = inb(chip->vendor.base + RDFIFO); ++ status = inb(chip->vendor.base + STAT); + i++; + if (i == TPM_MAX_TRIES) + return -EIO; +@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i + int status; + int i; + for (i = 0; i < TPM_MAX_TRIES; i++) { +- status = inb(chip->vendor->base + STAT); ++ status = inb(chip->vendor.base + STAT); + /* check the status-register if wait_for_bit is set */ + if (status & 1 << wait_for_bit) + break; +@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i + static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) + { + wait(chip, STAT_XFE); +- outb(sendbyte, chip->vendor->base + WRFIFO); ++ outb(sendbyte, chip->vendor.base + WRFIFO); + } + + /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more +@@ -204,7 +205,7 @@ recv_begin: + ret = wait(chip, STAT_RDA); + if (ret) + return -EIO; +- buf[i] = inb(chip->vendor->base + RDFIFO); ++ buf[i] = inb(chip->vendor.base + RDFIFO); + } + + if (buf[0] != TPM_VL_VER) { +@@ -219,7 +220,7 @@ recv_begin: + + for (i = 0; i < size; i++) { + wait(chip, STAT_RDA); +- buf[i] = inb(chip->vendor->base + RDFIFO); ++ buf[i] = inb(chip->vendor.base + RDFIFO); + } + + if ((size == 0x6D00) && (buf[1] == 0x80)) { +@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip + u8 count_high, count_low, count_4, count_3, count_2, count_1; + + /* Disabling Reset, LP and IRQC */ +- outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD); ++ outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); + + ret = empty_fifo(chip, 1); + if (ret) { +@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch + + static u8 tpm_inf_status(struct tpm_chip *chip) + { +- return inb(chip->vendor->base + STAT); ++ return inb(chip->vendor.base + STAT); + } + + static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); +@@ -346,7 +347,7 @@ static struct file_operations inf_ops = + .release = tpm_release, + }; + +-static struct tpm_vendor_specific tpm_inf = { ++static const struct tpm_vendor_specific tpm_inf = { + .recv = tpm_inf_recv, + .send = tpm_inf_send, + .cancel = tpm_inf_cancel, +@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s + int version[2]; + int productid[2]; + char chipname[20]; ++ struct tpm_chip *chip; + + /* read IO-ports through PnP */ + if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && +@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s + goto err_last; + } + /* publish my base address and request region */ +- tpm_inf.base = TPM_INF_BASE; + if (request_region +- (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { ++ (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { + rc = -EINVAL; + goto err_last; + } +- if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN, +- "tpm_infineon0") == NULL) { ++ if (request_region ++ (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { + rc = -EINVAL; + goto err_last; + } +@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s + + /* configure TPM with IO-ports */ + outb(IOLIMH, TPM_INF_ADDR); +- outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA); ++ outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); + outb(IOLIML, TPM_INF_ADDR); +- outb((tpm_inf.base & 0xff), TPM_INF_DATA); ++ outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); + + /* control if IO-ports are set correctly */ + outb(IOLIMH, TPM_INF_ADDR); +@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s + outb(IOLIML, TPM_INF_ADDR); + iol = inb(TPM_INF_DATA); + +- if ((ioh << 8 | iol) != tpm_inf.base) { ++ if ((ioh << 8 | iol) != TPM_INF_BASE) { + dev_err(&dev->dev, +- "Could not set IO-ports to 0x%lx\n", +- tpm_inf.base); ++ "Could not set IO-ports to 0x%x\n", ++ TPM_INF_BASE); + rc = -EIO; + goto err_release_region; + } +@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s + outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); + + /* disable RESET, LP and IRQC */ +- outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD); ++ outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); + + /* Finally, we're done, print some infos */ + dev_info(&dev->dev, "TPM found: " + "config base 0x%x, " + "io base 0x%x, " +- "chip version %02x%02x, " +- "vendor id %x%x (Infineon), " +- "product id %02x%02x" ++ "chip version 0x%02x%02x, " ++ "vendor id 0x%x%x (Infineon), " ++ "product id 0x%02x%02x" + "%s\n", + TPM_INF_ADDR, + TPM_INF_BASE, +@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s + vendorid[0], vendorid[1], + productid[0], productid[1], chipname); + +- rc = tpm_register_hardware(&dev->dev, &tpm_inf); +- if (rc < 0) { +- rc = -ENODEV; ++ if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { + goto err_release_region; + } ++ chip->vendor.base = TPM_INF_BASE; + return 0; + } else { + rc = -ENODEV; +@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s + } + + err_release_region: +- release_region(tpm_inf.base, TPM_INF_PORT_LEN); ++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); + release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); + + err_last: +@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove + struct tpm_chip *chip = pnp_get_drvdata(dev); + + if (chip) { +- release_region(chip->vendor->base, TPM_INF_PORT_LEN); ++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); ++ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); + tpm_remove_hardware(chip->dev); + } + } +@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = { + }, + .id_table = tpm_pnp_tbl, + .probe = tpm_inf_pnp_probe, +- .remove = tpm_inf_pnp_remove, ++ .remove = __devexit_p(tpm_inf_pnp_remove), + }; + + static int __init init_inf(void) +@@ -538,5 +539,5 @@ module_exit(cleanup_inf); + + MODULE_AUTHOR("Marcel Selhorst <selhorst@xxxxxxxxxxxxx>"); + MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); +-MODULE_VERSION("1.7"); ++MODULE_VERSION("1.8"); + MODULE_LICENSE("GPL"); +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c ./drivers/char/tpm/tpm_nsc.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c 2006-06-26 18:05:03.000000000 -0400 ++++ ./drivers/char/tpm/tpm_nsc.c 2006-06-26 18:16:33.000000000 -0400 +@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip + unsigned long stop; + + /* status immediately available check */ +- *data = inb(chip->vendor->base + NSC_STATUS); ++ *data = inb(chip->vendor.base + NSC_STATUS); + if ((*data & mask) == val) + return 0; + +@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip + stop = jiffies + 10 * HZ; + do { + msleep(TPM_TIMEOUT); +- *data = inb(chip->vendor->base + 1); ++ *data = inb(chip->vendor.base + 1); + if ((*data & mask) == val) + return 0; + } +@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm + unsigned long stop; + + /* status immediately available check */ +- status = inb(chip->vendor->base + NSC_STATUS); ++ status = inb(chip->vendor.base + NSC_STATUS); + if (status & NSC_STATUS_OBF) +- status = inb(chip->vendor->base + NSC_DATA); ++ status = inb(chip->vendor.base + NSC_DATA); + if (status & NSC_STATUS_RDY) + return 0; + +@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm + stop = jiffies + 100; + do { + msleep(TPM_TIMEOUT); +- status = inb(chip->vendor->base + NSC_STATUS); ++ status = inb(chip->vendor.base + NSC_STATUS); + if (status & NSC_STATUS_OBF) +- status = inb(chip->vendor->base + NSC_DATA); ++ status = inb(chip->vendor.base + NSC_DATA); + if (status & NSC_STATUS_RDY) + return 0; + } +@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip + return -EIO; + } + if ((data = +- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) { ++ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { + dev_err(chip->dev, "not in normal mode (0x%x)\n", + data); + return -EIO; +@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip + } + if (data & NSC_STATUS_F0) + break; +- *p = inb(chip->vendor->base + NSC_DATA); ++ *p = inb(chip->vendor.base + NSC_DATA); + } + + if ((data & NSC_STATUS_F0) == 0 && +@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip + dev_err(chip->dev, "F0 not set\n"); + return -EIO; + } +- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) { ++ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { + dev_err(chip->dev, + "expected end of command(0x%x)\n", data); + return -EIO; +@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip + * fix it. Not sure why this is needed, we followed the flow + * chart in the manual to the letter. + */ +- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); + + if (nsc_wait_for_ready(chip) != 0) + return -EIO; +@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip + return -EIO; + } + +- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); + if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { + dev_err(chip->dev, "IBR timeout\n"); + return -EIO; +@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip + "IBF timeout (while writing data)\n"); + return -EIO; + } +- outb(buf[i], chip->vendor->base + NSC_DATA); ++ outb(buf[i], chip->vendor.base + NSC_DATA); + } + + if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { + dev_err(chip->dev, "IBF timeout\n"); + return -EIO; + } +- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); + + return count; + } + + static void tpm_nsc_cancel(struct tpm_chip *chip) + { +- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND); ++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND); + } + + static u8 tpm_nsc_status(struct tpm_chip *chip) + { +- return inb(chip->vendor->base + NSC_STATUS); ++ return inb(chip->vendor.base + NSC_STATUS); + } + + static struct file_operations nsc_ops = { +@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = + + static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; + +-static struct tpm_vendor_specific tpm_nsc = { ++static const struct tpm_vendor_specific tpm_nsc = { + .recv = tpm_nsc_recv, + .send = tpm_nsc_send, + .cancel = tpm_nsc_cancel, +@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str + { + struct tpm_chip *chip = dev_get_drvdata(dev); + if ( chip ) { +- release_region(chip->vendor->base, 2); ++ release_region(chip->vendor.base, 2); + tpm_remove_hardware(chip->dev); + } + } +@@ -286,7 +286,8 @@ static int __init init_nsc(void) + int rc = 0; + int lo, hi; + int nscAddrBase = TPM_ADDR; +- ++ struct tpm_chip *chip; ++ unsigned long base; + + /* verify that it is a National part (SID) */ + if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) { +@@ -300,7 +301,7 @@ static int __init init_nsc(void) + + hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI); + lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO); +- tpm_nsc.base = (hi<<8) | lo; ++ base = (hi<<8) | lo; + + /* enable the DPM module */ + tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); +@@ -320,13 +321,15 @@ static int __init init_nsc(void) + if ((rc = platform_device_register(pdev)) < 0) + goto err_free_dev; + +- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) { ++ if (request_region(base, 2, "tpm_nsc0") == NULL ) { + rc = -EBUSY; + goto err_unreg_dev; + } + +- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0) ++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { ++ rc = -ENODEV; + goto err_rel_reg; ++ } + + dev_dbg(&pdev->dev, "NSC TPM detected\n"); + dev_dbg(&pdev->dev, +@@ -361,10 +364,12 @@ static int __init init_nsc(void) + "NSC TPM revision %d\n", + tpm_read_index(nscAddrBase, 0x27) & 0x1F); + ++ chip->vendor.base = base; ++ + return 0; + + err_rel_reg: +- release_region(tpm_nsc.base, 2); ++ release_region(base, 2); + err_unreg_dev: + platform_device_unregister(pdev); + err_free_dev: +diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c ./drivers/char/tpm/tpm_tis.c +--- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c 1969-12-31 19:00:00.000000000 -0500 ++++ ./drivers/char/tpm/tpm_tis.c 2006-06-26 18:16:33.000000000 -0400 +@@ -0,0 +1,665 @@ ++/* ++ * Copyright (C) 2005, 2006 IBM Corporation ++ * ++ * Authors: ++ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx> ++ * Kylene Hall <kjhall@xxxxxxxxxx> ++ * ++ * Device driver for TCG/TCPA TPM (trusted platform module). ++ * Specifications at www.trustedcomputinggroup.org ++ * ++ * This device driver implements the TPM interface as defined in ++ * the TCG TPM Interface Spec version 1.2, revision 1.0. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation, version 2 of the ++ * License. ++ */ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/pnp.h> ++#include <linux/interrupt.h> ++#include <linux/wait.h> ++#include "tpm.h" ++ ++#define TPM_HEADER_SIZE 10 ++ ++enum tis_access { ++ TPM_ACCESS_VALID = 0x80, ++ TPM_ACCESS_ACTIVE_LOCALITY = 0x20, ++ TPM_ACCESS_REQUEST_PENDING = 0x04, ++ TPM_ACCESS_REQUEST_USE = 0x02, ++}; ++ ++enum tis_status { ++ TPM_STS_VALID = 0x80, ++ TPM_STS_COMMAND_READY = 0x40, ++ TPM_STS_GO = 0x20, ++ TPM_STS_DATA_AVAIL = 0x10, ++ TPM_STS_DATA_EXPECT = 0x08, ++}; ++ ++enum tis_int_flags { ++ TPM_GLOBAL_INT_ENABLE = 0x80000000, ++ TPM_INTF_BURST_COUNT_STATIC = 0x100, ++ TPM_INTF_CMD_READY_INT = 0x080, ++ TPM_INTF_INT_EDGE_FALLING = 0x040, ++ TPM_INTF_INT_EDGE_RISING = 0x020, ++ TPM_INTF_INT_LEVEL_LOW = 0x010, ++ TPM_INTF_INT_LEVEL_HIGH = 0x008, ++ TPM_INTF_LOCALITY_CHANGE_INT = 0x004, ++ TPM_INTF_STS_VALID_INT = 0x002, ++ TPM_INTF_DATA_AVAIL_INT = 0x001, ++}; ++ ++enum tis_defaults { ++ TIS_MEM_BASE = 0xFED40000, ++ TIS_MEM_LEN = 0x5000, ++ TIS_SHORT_TIMEOUT = 750, /* ms */ ++ TIS_LONG_TIMEOUT = 2000, /* 2 sec */ ++}; ++ ++#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) ++#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) ++#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) ++#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) ++#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) ++#define TPM_STS(l) (0x0018 | ((l) << 12)) ++#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) ++ ++#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) ++#define TPM_RID(l) (0x0F04 | ((l) << 12)) ++ ++static LIST_HEAD(tis_chips); ++static DEFINE_SPINLOCK(tis_lock); ++ ++static int check_locality(struct tpm_chip *chip, int l) ++{ ++ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & ++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == ++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ++ return chip->vendor.locality = l; ++ ++ return -1; ++} ++ ++static void release_locality(struct tpm_chip *chip, int l, int force) ++{ ++ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) & ++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == ++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ++ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY, ++ chip->vendor.iobase + TPM_ACCESS(l)); ++} ++ ++static int request_locality(struct tpm_chip *chip, int l) ++{ ++ unsigned long stop; ++ long rc; ++ ++ if (check_locality(chip, l) >= 0) ++ return l; ++ ++ iowrite8(TPM_ACCESS_REQUEST_USE, ++ chip->vendor.iobase + TPM_ACCESS(l)); ++ ++ if (chip->vendor.irq) { ++ rc = wait_event_interruptible_timeout(chip->vendor.int_queue, ++ (check_locality ++ (chip, l) >= 0), ++ chip->vendor.timeout_a); ++ if (rc > 0) ++ return l; ++ ++ } else { ++ /* wait for burstcount */ ++ stop = jiffies + chip->vendor.timeout_a; ++ do { ++ if (check_locality(chip, l) >= 0) ++ return l; ++ msleep(TPM_TIMEOUT); ++ } ++ while (time_before(jiffies, stop)); ++ } ++ return -1; ++} ++ ++static u8 tpm_tis_status(struct tpm_chip *chip) ++{ ++ return ioread8(chip->vendor.iobase + ++ TPM_STS(chip->vendor.locality)); ++} ++ ++static void tpm_tis_ready(struct tpm_chip *chip) ++{ ++ /* this causes the current command to be aborted */ ++ iowrite8(TPM_STS_COMMAND_READY, ++ chip->vendor.iobase + TPM_STS(chip->vendor.locality)); ++} ++ ++static int get_burstcount(struct tpm_chip *chip) ++{ ++ unsigned long stop; ++ int burstcnt; ++ ++ /* wait for burstcount */ ++ /* which timeout value, spec has 2 answers (c & d) */ ++ stop = jiffies + chip->vendor.timeout_d; ++ do { ++ burstcnt = ioread8(chip->vendor.iobase + ++ TPM_STS(chip->vendor.locality) + 1); ++ burstcnt += ioread8(chip->vendor.iobase + ++ TPM_STS(chip->vendor.locality) + ++ 2) << 8; ++ if (burstcnt) ++ return burstcnt; ++ msleep(TPM_TIMEOUT); ++ } while (time_before(jiffies, stop)); ++ return -EBUSY; ++} ++ ++static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, ++ wait_queue_head_t *queue) ++{ ++ unsigned long stop; ++ long rc; ++ u8 status; ++ ++ /* check current status */ ++ status = tpm_tis_status(chip); ++ if ((status & mask) == mask) ++ return 0; ++ ++ if (chip->vendor.irq) { ++ rc = wait_event_interruptible_timeout(*queue, ++ ((tpm_tis_status ++ (chip) & mask) == ++ mask), timeout); ++ if (rc > 0) ++ return 0; ++ } else { ++ stop = jiffies + timeout; ++ do { ++ msleep(TPM_TIMEOUT); ++ status = tpm_tis_status(chip); ++ if ((status & mask) == mask) ++ return 0; ++ } while (time_before(jiffies, stop)); ++ } ++ return -ETIME; ++} ++ ++static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ int size = 0, burstcnt; ++ while (size < count && ++ wait_for_stat(chip, ++ TPM_STS_DATA_AVAIL | TPM_STS_VALID, ++ chip->vendor.timeout_c, ++ &chip->vendor.read_queue) ++ == 0) { ++ burstcnt = get_burstcount(chip); ++ for (; burstcnt > 0 && size < count; burstcnt--) ++ buf[size++] = ioread8(chip->vendor.iobase + ++ TPM_DATA_FIFO(chip->vendor. ++ locality)); ++ } ++ return size; ++} ++ ++static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ int size = 0; ++ int expected, status; ++ ++ if (count < TPM_HEADER_SIZE) { ++ size = -EIO; ++ goto out; ++ } ++ ++ /* read first 10 bytes, including tag, paramsize, and result */ ++ if ((size = ++ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { ++ dev_err(chip->dev, "Unable to read header\n"); ++ goto out; ++ } ++ ++ expected = be32_to_cpu(*(__be32 *) (buf + 2)); ++ if (expected > count) { ++ size = -EIO; ++ goto out; ++ } ++ ++ if ((size += ++ recv_data(chip, &buf[TPM_HEADER_SIZE], ++ expected - TPM_HEADER_SIZE)) < expected) { ++ dev_err(chip->dev, "Unable to read remainder of result\n"); ++ size = -ETIME; ++ goto out; ++ } ++ ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, ++ &chip->vendor.int_queue); ++ status = tpm_tis_status(chip); ++ if (status & TPM_STS_DATA_AVAIL) { /* retry? */ ++ dev_err(chip->dev, "Error left over data\n"); ++ size = -EIO; ++ goto out; ++ } ++ ++out: ++ tpm_tis_ready(chip); ++ release_locality(chip, chip->vendor.locality, 0); ++ return size; ++} ++ ++/* ++ * If interrupts are used (signaled by an irq set in the vendor structure) ++ * tpm.c can skip polling for the data to be available as the interrupt is ++ * waited for here ++ */ ++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) ++{ ++ int rc, status, burstcnt; ++ size_t count = 0; ++ u32 ordinal; ++ ++ if (request_locality(chip, 0) < 0) ++ return -EBUSY; ++ ++ status = tpm_tis_status(chip); ++ if ((status & TPM_STS_COMMAND_READY) == 0) { ++ tpm_tis_ready(chip); ++ if (wait_for_stat ++ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, ++ &chip->vendor.int_queue) < 0) { ++ rc = -ETIME; ++ goto out_err; ++ } ++ } ++ ++ while (count < len - 1) { ++ burstcnt = get_burstcount(chip); ++ for (; burstcnt > 0 && count < len - 1; burstcnt--) { ++ iowrite8(buf[count], chip->vendor.iobase + ++ TPM_DATA_FIFO(chip->vendor.locality)); ++ count++; ++ } ++ ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, ++ &chip->vendor.int_queue); ++ status = tpm_tis_status(chip); ++ if ((status & TPM_STS_DATA_EXPECT) == 0) { ++ rc = -EIO; ++ goto out_err; ++ } ++ } ++ ++ /* write last byte */ ++ iowrite8(buf[count], ++ chip->vendor.iobase + ++ TPM_DATA_FIFO(chip->vendor.locality)); ++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, ++ &chip->vendor.int_queue); ++ status = tpm_tis_status(chip); ++ if ((status & TPM_STS_DATA_EXPECT) != 0) { ++ rc = -EIO; ++ goto out_err; ++ } ++ ++ /* go and do it */ ++ iowrite8(TPM_STS_GO, ++ chip->vendor.iobase + TPM_STS(chip->vendor.locality)); ++ ++ if (chip->vendor.irq) { ++ ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); ++ if (wait_for_stat ++ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |