[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 Isaku Yamahata <yamahata@xxxxxxxxxxxxx> # Date 1218077854 -32400 # Node ID a39913db6e51d060e312c27ef46d1442390bbf67 # Parent 7affdebb7a1ed4f80fb46c679f25c642b1a67034 # Parent eff5fcfa69bc601f1872a808d7a2134c460f2135 merge with xen-unstable.hg --- tools/examples/stubdom-ExampleHVMDomain | 14 .hgignore | 20 .hgtags | 2 Config.mk | 6 Makefile | 2 README | 22 docs/Docs.mk | 4 docs/Makefile | 16 docs/misc/vtd.txt | 9 docs/src/user.tex | 8 docs/xen-api/Makefile | 8 docs/xen-api/coversheet.tex | 4 docs/xen-api/revision-history.tex | 9 docs/xen-api/xenapi-coversheet.tex | 4 docs/xen-api/xenapi-datamodel-graph.dot | 7 docs/xen-api/xenapi-datamodel.tex | 1259 +++++++++++++ extras/mini-os/fs-front.c | 266 ++ extras/mini-os/gntmap.c | 252 ++ extras/mini-os/include/fs.h | 5 extras/mini-os/include/gntmap.h | 35 extras/mini-os/include/lib.h | 3 extras/mini-os/lib/sys.c | 12 extras/mini-os/minios.mk | 1 extras/mini-os/pcifront.c | 13 stubdom/Makefile | 38 stubdom/README | 18 stubdom/stubdom-dm | 6 tools/Makefile | 15 tools/blktap/Makefile | 3 tools/blktap/lib/Makefile | 2 tools/console/Makefile | 2 tools/console/daemon/io.c | 14 tools/examples/Makefile | 18 tools/examples/README | 4 tools/examples/xend-config.sxp | 4 tools/examples/xmexample.hvm | 5 tools/examples/xmexample.hvm-dm | 14 tools/examples/xmexample.hvm-stubdom | 4 tools/examples/xmexample.pv-grub | 212 ++ tools/examples/xmexample.vti | 5 tools/examples/xmexample3 | 24 tools/firmware/extboot/Makefile | 2 tools/firmware/hvmloader/Makefile | 8 tools/firmware/hvmloader/acpi/acpi2_0.h | 2 tools/firmware/hvmloader/acpi/build.c | 41 tools/firmware/hvmloader/hvmloader.c | 9 tools/firmware/hvmloader/util.h | 2 tools/firmware/rombios/32bit/32bitbios.c | 2 tools/firmware/rombios/32bit/Makefile | 9 tools/firmware/rombios/32bit/tcgbios/Makefile | 2 tools/firmware/rombios/32bit/tcgbios/tcgbios.c | 47 tools/firmware/rombios/32bit/tcgbios/tcgbios.h | 41 tools/firmware/rombios/32bit/util.c | 72 tools/firmware/rombios/32bit/util.h | 3 tools/firmware/rombios/32bitgateway.c | 12 tools/firmware/rombios/32bitprotos.h | 6 tools/firmware/rombios/Makefile | 3 tools/firmware/rombios/rombios.c | 154 - tools/fs-back/fs-backend.c | 36 tools/fs-back/fs-backend.h | 17 tools/fs-back/fs-ops.c | 143 - tools/fs-back/fs-xenbus.c | 19 tools/include/xen-sys/MiniOS/privcmd.h | 2 tools/ioemu/block-vbd.c | 4 tools/ioemu/hw/pass-through.c | 329 +-- tools/ioemu/hw/pass-through.h | 8 tools/ioemu/hw/pc.c | 19 tools/ioemu/hw/pci.c | 7 tools/ioemu/hw/pt-msi.c | 6 tools/ioemu/hw/serial.c | 1 tools/ioemu/hw/vga.c | 4 tools/ioemu/vl.c | 2 tools/libaio/src/Makefile | 2 tools/libxc/xc_dom_boot.c | 30 tools/libxc/xc_domain_save.c | 54 tools/libxc/xc_hvm_build.c | 34 tools/libxc/xc_linux.c | 35 tools/libxc/xc_minios.c | 150 + tools/libxc/xc_netbsd.c | 53 tools/libxc/xc_physdev.c | 6 tools/libxc/xc_private.h | 5 tools/libxc/xc_solaris.c | 35 tools/libxc/xenctrl.h | 2 tools/pygrub/src/pygrub | 2 tools/python/xen/lowlevel/xc/xc.c | 3 tools/python/xen/util/pci.py | 116 - tools/python/xen/util/utils.py | 44 tools/python/xen/xend/XendDomainInfo.py | 30 tools/python/xen/xend/image.py | 10 tools/python/xen/xend/server/pciif.py | 43 tools/python/xen/xm/console.py | 63 tools/python/xen/xm/create.dtd | 8 tools/python/xen/xm/create.py | 65 tools/python/xen/xm/main.py | 130 + tools/python/xen/xm/shutdown.py | 5 tools/python/xen/xm/xenapi_create.py | 81 tools/xenmon/Makefile | 2 tools/xenstat/libxenstat/Makefile | 2 tools/xenstat/libxenstat/src/xenstat.c | 2 unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c | 4 xen/Makefile | 6 xen/arch/ia64/xen/domain.c | 5 xen/arch/ia64/xen/irq.c | 3 xen/arch/x86/acpi/cpufreq/utility.c | 10 xen/arch/x86/acpi/pmstat.c | 6 xen/arch/x86/domain.c | 1 xen/arch/x86/domain_build.c | 1 xen/arch/x86/domctl.c | 15 xen/arch/x86/hvm/io.c | 2 xen/arch/x86/hvm/stdvga.c | 34 xen/arch/x86/hvm/svm/svm.c | 7 xen/arch/x86/hvm/vmx/vmx.c | 2 xen/arch/x86/io_apic.c | 8 xen/arch/x86/irq.c | 3 xen/arch/x86/mm.c | 38 xen/arch/x86/mm/shadow/multi.c | 23 xen/arch/x86/msi.c | 17 xen/arch/x86/numa.c | 26 xen/arch/x86/physdev.c | 9 xen/arch/x86/platform_hypercall.c | 31 xen/arch/x86/setup.c | 12 xen/arch/x86/shutdown.c | 13 xen/arch/x86/time.c | 180 - xen/arch/x86/x86_64/physdev.c | 9 xen/arch/x86/x86_emulate/x86_emulate.c | 2 xen/common/compat/grant_table.c | 1 xen/common/domain.c | 4 xen/common/event_channel.c | 57 xen/common/keyhandler.c | 58 xen/common/page_alloc.c | 93 xen/common/shutdown.c | 5 xen/drivers/char/console.c | 3 xen/drivers/passthrough/amd/iommu_acpi.c | 233 +- xen/drivers/passthrough/amd/iommu_detect.c | 227 -- xen/drivers/passthrough/amd/iommu_init.c | 236 ++ xen/drivers/passthrough/amd/iommu_intr.c | 17 xen/drivers/passthrough/amd/iommu_map.c | 2 xen/drivers/passthrough/amd/pci_amd_iommu.c | 289 -- xen/drivers/passthrough/iommu.c | 72 xen/drivers/passthrough/pci.c | 118 - xen/drivers/passthrough/vtd/dmar.c | 57 xen/drivers/passthrough/vtd/extern.h | 1 xen/drivers/passthrough/vtd/iommu.c | 152 - xen/drivers/passthrough/vtd/utils.c | 136 + xen/include/acpi/cpufreq/processor_perf.h | 2 xen/include/asm-ia64/config.h | 2 xen/include/asm-x86/amd-iommu.h | 8 xen/include/asm-x86/config.h | 2 xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 27 xen/include/asm-x86/io_apic.h | 2 xen/include/asm-x86/p2m.h | 2 xen/include/public/io/fsif.h | 24 xen/include/public/xen.h | 1 xen/include/xen/iommu.h | 2 xen/include/xen/irq.h | 2 xen/include/xen/sched.h | 4 xen/include/xen/shutdown.h | 2 xen/include/xen/spinlock.h | 4 158 files changed, 4775 insertions(+), 1930 deletions(-) diff -r 7affdebb7a1e -r a39913db6e51 .hgignore --- a/.hgignore Thu Aug 07 11:47:34 2008 +0900 +++ b/.hgignore Thu Aug 07 11:57:34 2008 +0900 @@ -21,8 +21,7 @@ ^[^/]*\.bz2$ ^\.config$ ^\.pc -^TAGS$ -^tags$ +(^|/)(tags|TAGS)$ ^build-.*$ ^dist/.*$ ^docs/.*\.aux$ @@ -60,10 +59,13 @@ ^docs/xen-api/vm_lifecycle.eps$ ^docs/xen-api/xenapi-datamodel-graph.eps$ ^docs/xen-api/xenapi.out$ -^extras/mini-os/h/hypervisor-ifs$ -^extras/mini-os/h/xen-public$ +^extras/mini-os/arch/ia64/gen_off.s$ +^extras/mini-os/include/mini-os$ +^extras/mini-os/include/ia64/mini-os$ +^extras/mini-os/include/ia64/offsets.h$ +^extras/mini-os/include/x86/mini-os$ +^extras/mini-os/include/xen$ ^extras/mini-os/mini-os.*$ -^extras/mini-os/*-stubdom.*$ ^install/.*$ ^linux-[^/]*-paravirt/.*$ ^linux-2.6[^/]*/.*$ @@ -91,13 +93,17 @@ ^stubdom/libxc$ ^stubdom/lwip-.*$ ^stubdom/mini-os-.*$ +^stubdom/mk-headers$ ^stubdom/newlib-.*$ ^stubdom/pciutils-.*$ ^stubdom/zlib-.*$ ^stubdom/grub-cvs$ ^stubdom/grub/stage2$ ^stubdom/grub/netboot$ -^tools/.*/TAGS$ +^stubdom/grub/dirs$ +^stubdom/lwip/ +^stubdom/ioemu/ +^stubdom/grub-upstream/ ^tools/.*/build/lib.*/.*\.py$ ^tools/blktap/Makefile\.smh$ ^tools/blktap/drivers/blktapctrl$ @@ -253,7 +259,6 @@ ^xen/\.banner.*$ ^xen/BLOG$ ^xen/System.map$ -^xen/TAGS$ ^xen/arch/x86/asm-offsets\.s$ ^xen/arch/x86/boot/mkelf32$ ^xen/arch/x86/xen\.lds$ @@ -271,7 +276,6 @@ ^xen/include/xen/acm_policy\.h$ ^xen/include/xen/banner\.h$ ^xen/include/xen/compile\.h$ -^xen/tags$ ^xen/tools/figlet/figlet$ ^xen/tools/symbols$ ^xen/xen$ diff -r 7affdebb7a1e -r a39913db6e51 .hgtags --- a/.hgtags Thu Aug 07 11:47:34 2008 +0900 +++ b/.hgtags Thu Aug 07 11:57:34 2008 +0900 @@ -25,3 +25,5 @@ c5deb251b9dcece9e466a48a66d3528ca1797db4 c5deb251b9dcece9e466a48a66d3528ca1797db4 3.2.0-rc4 36bb2ab4722733d919d32e4555eb46cc6a06cb8f 3.2.0-rc5 9facc624a238f2b9437b07fa28ff65884aa867f2 3.2.0-rc6 +c3494402098e26507fc61a6579832c0149351d6a 3.3.0-rc1 +dde12ff94c96331668fe38a7b09506fa94d03c34 3.3.0-rc2 diff -r 7affdebb7a1e -r a39913db6e51 Config.mk --- a/Config.mk Thu Aug 07 11:47:34 2008 +0900 +++ b/Config.mk Thu Aug 07 11:57:34 2008 +0900 @@ -19,6 +19,8 @@ HOSTCFLAGS += -fno-strict-aliasing DISTDIR ?= $(XEN_ROOT)/dist DESTDIR ?= / +DOCDIR ?= /usr/share/doc/xen +MANDIR ?= /usr/share/man # Allow phony attribute to be listed as dependency rather than fake target .PHONY: .phony @@ -84,7 +86,11 @@ QEMU_REMOTE=http://xenbits.xensource.com # Mercurial in-tree version, or a local directory, or a git URL. # CONFIG_QEMU ?= ioemu # CONFIG_QEMU ?= ../qemu-xen.git +ifeq ($(XEN_TARGET_ARCH),ia64) +CONFIG_QEMU ?= ioemu +else CONFIG_QEMU ?= $(QEMU_REMOTE) +endif # Optional components XENSTAT_XENTOP ?= y diff -r 7affdebb7a1e -r a39913db6e51 Makefile --- a/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -149,7 +149,7 @@ help: @echo ' trees then make dist' @echo ' xen - build and install Xen hypervisor' @echo ' tools - build and install tools' - @echo ' stubdomain - build and install the stubdomain images' + @echo ' stubdom - build and install the stubdomain images' @echo ' kernels - build and install guest kernels' @echo ' kbuild - synonym for make kernels' @echo ' docs - build and install user documentation' diff -r 7affdebb7a1e -r a39913db6e51 README --- a/README Thu Aug 07 11:47:34 2008 +0900 +++ b/README Thu Aug 07 11:57:34 2008 +0900 @@ -1,10 +1,10 @@ ################################# - __ __ _____ _____ - \ \/ /___ _ __ |___ / |___ / - \ // _ \ '_ \ |_ \ |_ \ - / \ __/ | | | ___) | ___) | - /_/\_\___|_| |_| |____(_)____/ - + __ __ _ _ ___ + \ \/ /___ _ __ | || | / _ \ + \ // _ \ '_ \ | || |_| | | | + / \ __/ | | | |__ _| |_| | + /_/\_\___|_| |_| |_|(_)___/ + ################################# http://www.xen.org/ @@ -21,7 +21,7 @@ by the original Xen development team to by the original Xen development team to build enterprise products around Xen. -The 3.3 release offers excellent performance, hardware support and +The 4.0 release offers excellent performance, hardware support and enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and live relocation of VMs. Ports to Linux 2.6, Linux 2.4, NetBSD, FreeBSD and Solaris are available from the community. @@ -54,8 +54,8 @@ 2. Configure your bootloader to boot Xen /boot/grub/menu.lst: edit this file to include an entry like the following: - title Xen 3.3 / XenLinux 2.6 - kernel /boot/xen-3.3.gz console=vga + title Xen 4.0 / XenLinux 2.6 + kernel /boot/xen-4.0.gz console=vga module /boot/vmlinuz-2.6-xen root=<root-dev> ro console=tty0 module /boot/initrd-2.6-xen.img @@ -74,7 +74,7 @@ 2. Configure your bootloader to boot Xen 32MB memory for internal use, which is not available for allocation to virtual machines. -3. Reboot your system and select the "Xen 3.3 / XenLinux 2.6" menu +3. Reboot your system and select the "Xen 4.0 / XenLinux 2.6" menu option. After booting Xen, Linux will start and your initialisation scripts should execute in the usual way. @@ -224,6 +224,6 @@ to modify grub.conf to use tboot to laun to modify grub.conf to use tboot to launch Xen. There are optional targets as part of Xen's top-level makefile that will -downlaod and build tboot: install-tboot, build-tboot, dist-tboot, clean-tboot. +download and build tboot: install-tboot, build-tboot, dist-tboot, clean-tboot. These will download the latest tar file from the SourceForge site using wget, then build/install/dist according to Xen's settings. diff -r 7affdebb7a1e -r a39913db6e51 docs/Docs.mk --- a/docs/Docs.mk Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/Docs.mk Thu Aug 07 11:57:34 2008 +0900 @@ -7,7 +7,3 @@ POD2MAN := pod2man POD2MAN := pod2man DOT := dot NEATO := neato - -pkgdocdir := /usr/share/doc/xen -mandir := /usr/share/man - diff -r 7affdebb7a1e -r a39913db6e51 docs/Makefile --- a/docs/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -80,17 +80,17 @@ distclean: clean .PHONY: install install: all - rm -rf $(DESTDIR)$(pkgdocdir) - $(INSTALL_DIR) $(DESTDIR)$(pkgdocdir) + rm -rf $(DESTDIR)$(DOCDIR) + $(INSTALL_DIR) $(DESTDIR)$(DOCDIR) $(MAKE) -C xen-api install - cp -dR ps $(DESTDIR)$(pkgdocdir) - cp -dR pdf $(DESTDIR)$(pkgdocdir) - $(INSTALL_DIR) $(DESTDIR)$(mandir) - cp -dR man1 $(DESTDIR)$(mandir) - cp -dR man5 $(DESTDIR)$(mandir) - [ ! -d html ] || cp -dR html $(DESTDIR)$(pkgdocdir) + cp -dR ps $(DESTDIR)$(DOCDIR) + cp -dR pdf $(DESTDIR)$(DOCDIR) + $(INSTALL_DIR) $(DESTDIR)$(MANDIR) + cp -dR man1 $(DESTDIR)$(MANDIR) + cp -dR man5 $(DESTDIR)$(MANDIR) + [ ! -d html ] || cp -dR html $(DESTDIR)$(DOCDIR) pdf/%.pdf: ps/%.ps $(INSTALL_DIR) $(@D) diff -r 7affdebb7a1e -r a39913db6e51 docs/misc/vtd.txt --- a/docs/misc/vtd.txt Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/misc/vtd.txt Thu Aug 07 11:57:34 2008 +0900 @@ -2,7 +2,7 @@ Authors : Allen Kay <allen.m.kay@inte Authors : Allen Kay <allen.m.kay@xxxxxxxxx> Weidong Han <weidong.han@xxxxxxxxx> Created : October-24-2007 -Updated : May-07-2008 +Updated : August-06-2008 How to turn on VT-d in Xen -------------------------- @@ -21,7 +21,7 @@ 11) "hide" pci device from dom0 as follo title Xen-Fedora Core (2.6.18-xen) root (hd0,0) - kernel /boot/xen.gz com1=115200,8n1 console=com1 + kernel /boot/xen.gz com1=115200,8n1 console=com1 iommu=1 module /boot/vmlinuz-2.6.18.8-xen root=LABEL=/ ro xencons=ttyS console=tty0 console=ttyS0, pciback.hide=(01:00.0)(03:00.0) module /boot/initrd-2.6.18-xen.img @@ -30,6 +30,11 @@ 13) add "pci" line in /etc/xen/hvm.conf pci = [ '01:00.0', '03:00.0' ] 15) start hvm guest and use "lspci" to see the passthru device and "ifconfig" to see if IP address has been assigned to NIC devices. + + +Enable MSI/MSI-x for assigned devices +------------------------------------- +Add "msi=1" option in kernel line of host grub. Caveat on Conventional PCI Device Passthrough diff -r 7affdebb7a1e -r a39913db6e51 docs/src/user.tex --- a/docs/src/user.tex Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/src/user.tex Thu Aug 07 11:57:34 2008 +0900 @@ -4204,11 +4204,9 @@ writing to the VGA console after domain enabled by the BIOS. \item [ apic=bigsmp,default,es7000,summit ] Specify NUMA platform. This can usually be probed automatically. -\item [ dma\_bits=xxx ] Specify width of DMA - addresses in bits. Default is 30 bits (addresses up to 1GB are DMAable). -\item [ dma\_emergency\_pool=xxx ] Specify lower bound on size of DMA - pool below which ordinary allocations will fail rather than fall - back to allocating from the DMA pool. +\item [ dma\_bits=xxx ] Specify width of DMA addresses in bits. This + is used in NUMA systems to prevent this special DMA memory from + being exhausted in one node when remote nodes have available memory. \end{description} In addition, the following options may be specified on the Xen command diff -r 7affdebb7a1e -r a39913db6e51 docs/xen-api/Makefile --- a/docs/xen-api/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/xen-api/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -16,11 +16,11 @@ build: xenapi.pdf xenapi.ps build: xenapi.pdf xenapi.ps install: - $(INSTALL_DIR) $(DESTDIR)$(pkgdocdir)/ps - $(INSTALL_DIR) $(DESTDIR)$(pkgdocdir)/pdf + $(INSTALL_DIR) $(DESTDIR)$(DOCDIR)/ps + $(INSTALL_DIR) $(DESTDIR)$(DOCDIR)/pdf - [ -e xenapi.ps ] && cp xenapi.ps $(DESTDIR)$(pkgdocdir)/ps || true - [ -e xenapi.pdf ] && cp xenapi.pdf $(DESTDIR)$(pkgdocdir)/pdf || true + [ -e xenapi.ps ] && cp xenapi.ps $(DESTDIR)$(DOCDIR)/ps || true + [ -e xenapi.pdf ] && cp xenapi.pdf $(DESTDIR)$(DOCDIR)/pdf || true xenapi.dvi: $(TEX) $(EPS) $(EPSDOT) $(LATEX) xenapi.tex diff -r 7affdebb7a1e -r a39913db6e51 docs/xen-api/coversheet.tex --- a/docs/xen-api/coversheet.tex Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/xen-api/coversheet.tex Thu Aug 07 11:57:34 2008 +0900 @@ -50,7 +50,7 @@ Hollis Blanchard, IBM & Alastair Tse, Xe Hollis Blanchard, IBM & Alastair Tse, XenSource \\ Mike Day, IBM & Daniel Veillard, Red Hat \\ Jim Fehlig, Novell & Tom Wilkie, University of Cambridge \\ -Jon Harrop, XenSource & \\ +Jon Harrop, XenSource & Yosuke Iwamatsu, NEC \\ \end{tabular} \end{large} @@ -60,4 +60,4 @@ Jon Harrop, XenSource & \\ \legalnotice{} \newpage -\pagestyle{fancy} \ No newline at end of file +\pagestyle{fancy} diff -r 7affdebb7a1e -r a39913db6e51 docs/xen-api/revision-history.tex --- a/docs/xen-api/revision-history.tex Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/xen-api/revision-history.tex Thu Aug 07 11:57:34 2008 +0900 @@ -47,5 +47,14 @@ \end{flushleft} \end{minipage}\\ \hline + 1.0.6 & 24th Jul. 08 & Y. Iwamatsu & + \begin{minipage}[t]{7cm} + \begin{flushleft} + Added definitions of new classes DPCI and PPCI. Updated the table + and the diagram representing relationships between classes. + Added host.PPCIs and VM.DPCIs fields. + \end{flushleft} + \end{minipage}\\ + \hline \end{tabular} \end{center} diff -r 7affdebb7a1e -r a39913db6e51 docs/xen-api/xenapi-coversheet.tex --- a/docs/xen-api/xenapi-coversheet.tex Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/xen-api/xenapi-coversheet.tex Thu Aug 07 11:57:34 2008 +0900 @@ -17,12 +17,12 @@ \newcommand{\coversheetlogo}{xen.eps} %% Document date -\newcommand{\datestring}{11th February 2008} +\newcommand{\datestring}{24th July 2008} \newcommand{\releasestatement}{Stable Release} %% Document revision -\newcommand{\revstring}{API Revision 1.0.5} +\newcommand{\revstring}{API Revision 1.0.6} %% Document authors \newcommand{\docauthors}{ diff -r 7affdebb7a1e -r a39913db6e51 docs/xen-api/xenapi-datamodel-graph.dot --- a/docs/xen-api/xenapi-datamodel-graph.dot Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/xen-api/xenapi-datamodel-graph.dot Thu Aug 07 11:57:34 2008 +0900 @@ -14,7 +14,7 @@ fontname="Verdana"; node [ shape=box ]; session VM host network VIF PIF SR VDI VBD PBD user XSPolicy ACMPolicy; node [shape=ellipse]; PIF_metrics VIF_metrics VM_metrics VBD_metrics PBD_metrics VM_guest_metrics host_metrics; -node [shape=box]; host_cpu console +node [shape=box]; DPCI PPCI host_cpu console session -> host [ arrowhead="none" ] session -> user [ arrowhead="none" ] VM -> VM_metrics [ arrowhead="none" ] @@ -22,7 +22,7 @@ VM -> console [ arrowhead="crow" ] VM -> console [ arrowhead="crow" ] host -> PBD [ arrowhead="crow", arrowtail="none" ] host -> host_metrics [ arrowhead="none" ] -host -> host_cpu [ arrowhead="none" ] +host -> host_cpu [ arrowhead="crow", arrowtail="none" ] VIF -> VM [ arrowhead="none", arrowtail="crow" ] VIF -> network [ arrowhead="none", arrowtail="crow" ] VIF -> VIF_metrics [ arrowhead="none" ] @@ -38,4 +38,7 @@ VBD -> VBD_metrics [ arrowhead="none" ] VBD -> VBD_metrics [ arrowhead="none" ] XSPolicy -> host [ arrowhead="none" ] XSPolicy -> ACMPolicy [ arrowhead="none" ] +DPCI -> VM [ arrowhead="none", arrowtail="crow" ] +DPCI -> PPCI [ arrowhead="none" ] +PPCI -> host [ arrowhead="none", arrowtail="crow" ] } diff -r 7affdebb7a1e -r a39913db6e51 docs/xen-api/xenapi-datamodel.tex --- a/docs/xen-api/xenapi-datamodel.tex Thu Aug 07 11:47:34 2008 +0900 +++ b/docs/xen-api/xenapi-datamodel.tex Thu Aug 07 11:57:34 2008 +0900 @@ -44,6 +44,8 @@ Name & Description \\ {\tt crashdump} & A VM crashdump \\ {\tt VTPM} & A virtual TPM device \\ {\tt console} & A console \\ +{\tt DPCI} & A pass-through PCI device \\ +{\tt PPCI} & A physical PCI device \\ {\tt user} & A user of the system \\ {\tt debug} & A basic class for testing \\ {\tt XSPolicy} & A class for handling Xen Security Policies \\ @@ -70,6 +72,8 @@ SR.VDIs & VDI.SR & many-to-one\\ SR.VDIs & VDI.SR & many-to-one\\ VTPM.VM & VM.VTPMs & one-to-many\\ console.VM & VM.consoles & one-to-many\\ +DPCI.VM & VM.DPCIs & one-to-many\\ +PPCI.host & host.PPCIs & one-to-many\\ host.resident\_VMs & VM.resident\_on & many-to-one\\ host.host\_CPUs & host\_cpu.host & many-to-one\\ \hline @@ -1402,6 +1406,7 @@ Quals & Field & Type & Description \\ $\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & virtual block devices \\ $\mathit{RO}_\mathit{run}$ & {\tt crash\_dumps} & (crashdump ref) Set & crash dumps associated with this VM \\ $\mathit{RO}_\mathit{run}$ & {\tt VTPMs} & (VTPM ref) Set & virtual TPMs \\ +$\mathit{RO}_\mathit{run}$ & {\tt DPCIs} & (DPCI ref) Set & pass-through PCI devices \\ $\mathit{RW}$ & {\tt PV/bootloader} & string & name of or path to bootloader \\ $\mathit{RW}$ & {\tt PV/kernel} & string & path to the kernel \\ $\mathit{RW}$ & {\tt PV/ramdisk} & string & path to the initrd \\ @@ -3406,6 +3411,38 @@ Get the VTPMs field of the given VM. \noindent {\bf Return Type:} {\tt (VTPM ref) Set +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_DPCIs} + +{\bf Overview:} +Get the DPCIs field of the given VM. + + \noindent {\bf Signature:} +\begin{verbatim} ((DPCI ref) Set) get_DPCIs (session_id s, VM ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt VM ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(DPCI ref) Set } @@ -5480,6 +5517,7 @@ Quals & Field & Type & Description \\ $\mathit{RW}$ & {\tt suspend\_image\_sr} & SR ref & The SR in which VDIs for suspend images are created \\ $\mathit{RW}$ & {\tt crash\_dump\_sr} & SR ref & The SR in which VDIs for crash dumps are created \\ $\mathit{RO}_\mathit{run}$ & {\tt PBDs} & (PBD ref) Set & physical blockdevices \\ +$\mathit{RO}_\mathit{run}$ & {\tt PPCIs} & (PPCI ref) Set & physical PCI devices \\ $\mathit{RO}_\mathit{run}$ & {\tt host\_CPUs} & (host\_cpu ref) Set & The physical CPUs on this host \\ $\mathit{RO}_\mathit{run}$ & {\tt metrics} & host\_metrics ref & metrics associated with this host \\ \hline @@ -6767,6 +6805,38 @@ Get the PBDs field of the given host. \noindent {\bf Return Type:} {\tt (PBD ref) Set +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_PPCIs} + +{\bf Overview:} +Get the PPCIs field of the given host. + + \noindent {\bf Signature:} +\begin{verbatim} ((PPCI ref) Set) get_PPCIs (session_id s, host ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt host ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(PPCI ref) Set } @@ -14464,6 +14534,1195 @@ all fields from the object \vspace{1cm} \newpage +\section{Class: DPCI} +\subsection{Fields for class: DPCI} +\begin{longtable}{|lllp{0.38\textwidth}|} +\hline +\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf DPCI} \\ +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A +pass-through PCI device.}} \\ +\hline +Quals & Field & Type & Description \\ +\hline +$\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ +$\mathit{RO}_\mathit{inst}$ & {\tt VM} & VM ref & the virtual machine \\ +$\mathit{RO}_\mathit{inst}$ & {\tt PPCI} & PPCI ref & the physical PCI device \\ +$\mathit{RO}_\mathit{inst}$ & {\tt hotplug\_slot} & int & the slot number to which this PCI device is inserted \\ +$\mathit{RO}_\mathit{run}$ & {\tt virtual\_domain} & int & the virtual domain number \\ +$\mathit{RO}_\mathit{run}$ & {\tt virtual\_bus} & int & the virtual bus number \\ +$\mathit{RO}_\mathit{run}$ & {\tt virtual\_slot} & int & the virtual slot number \\ +$\mathit{RO}_\mathit{run}$ & {\tt virtual\_func} & int & the virtual func number \\ +$\mathit{RO}_\mathit{run}$ & {\tt virtual\_name} & string & the virtual PCI name \\ +\hline +\end{longtable} +\subsection{RPCs associated with class: DPCI} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the DPCIs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((DPCI ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(DPCI ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_uuid} + +{\bf Overview:} +Get the uuid field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_uuid (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_VM} + +{\bf Overview:} +Get the VM field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} (VM ref) get_VM (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +VM ref +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_PPCI} + +{\bf Overview:} +Get the PPCI field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} (PPCI ref) get_PPCI (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +PPCI ref +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_hotplug\_slot} + +{\bf Overview:} +Get the hotplug\_slot field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_hotplug_slot (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_virtual\_domain} + +{\bf Overview:} +Get the virtual\_domain field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_virtual_domain (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_virtual\_bus} + +{\bf Overview:} +Get the virtual\_bus field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_virtual_bus (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_virtual\_slot} + +{\bf Overview:} +Get the virtual\_slot field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_virtual_slot (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_virtual\_func} + +{\bf Overview:} +Get the virtual\_func field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_virtual_func (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_virtual\_name} + +{\bf Overview:} +Get the virtual\_name field of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_virtual_name (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~create} + +{\bf Overview:} +Create a new DPCI instance, and return its handle. + + \noindent {\bf Signature:} +\begin{verbatim} (DPCI ref) create (session_id s, DPCI record args)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI record } & args & All constructor arguments \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +DPCI ref +} + + +reference to the newly created object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~destroy} + +{\bf Overview:} +Destroy the specified DPCI instance. + + \noindent {\bf Signature:} +\begin{verbatim} void destroy (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +void +} + + +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_by\_uuid} + +{\bf Overview:} +Get a reference to the DPCI instance with the specified UUID. + + \noindent {\bf Signature:} +\begin{verbatim} (DPCI ref) get_by_uuid (session_id s, string uuid)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt string } & uuid & UUID of object to return \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +DPCI ref +} + + +reference to the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_record} + +{\bf Overview:} +Get a record containing the current state of the given DPCI. + + \noindent {\bf Signature:} +\begin{verbatim} (DPCI record) get_record (session_id s, DPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt DPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +DPCI record +} + + +all fields from the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} + +\vspace{1cm} +\newpage +\section{Class: PPCI} +\subsection{Fields for class: PPCI} +\begin{longtable}{|lllp{0.38\textwidth}|} +\hline +\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf PPCI} \\ +\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A +physical PCI device.}} \\ +\hline +Quals & Field & Type & Description \\ +\hline +$\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object reference \\ +$\mathit{RO}_\mathit{run}$ & {\tt host} & host ref & the physical machine to which this PPCI is connected \\ +$\mathit{RO}_\mathit{run}$ & {\tt domain} & int & the domain number \\ +$\mathit{RO}_\mathit{run}$ & {\tt bus} & int & the bus number \\ +$\mathit{RO}_\mathit{run}$ & {\tt slot} & int & the slot number \\ +$\mathit{RO}_\mathit{run}$ & {\tt func} & int & the func number \\ +$\mathit{RO}_\mathit{run}$ & {\tt name} & string & the PCI name \\ +$\mathit{RO}_\mathit{run}$ & {\tt vendor\_id} & int & the vendor ID \\ +$\mathit{RO}_\mathit{run}$ & {\tt vendor\_name} & string & the vendor name \\ +$\mathit{RO}_\mathit{run}$ & {\tt device\_id} & int & the device ID \\ +$\mathit{RO}_\mathit{run}$ & {\tt device\_name} & string & the device name \\ +$\mathit{RO}_\mathit{run}$ & {\tt revision\_id} & int & the revision ID \\ +$\mathit{RO}_\mathit{run}$ & {\tt class\_code} & int & the class code \\ +$\mathit{RO}_\mathit{run}$ & {\tt class\_name} & string & the class name \\ +$\mathit{RO}_\mathit{run}$ & {\tt subsystem\_vendor\_id} & int & the subsystem vendor ID \\ +$\mathit{RO}_\mathit{run}$ & {\tt subsystem\_vendor\_name} & string & the subsystem vendor name \\ +$\mathit{RO}_\mathit{run}$ & {\tt subsystem\_id} & int & the subsystem ID \\ +$\mathit{RO}_\mathit{run}$ & {\tt subsystem\_name} & string & the subsystem name \\ +$\mathit{RO}_\mathit{run}$ & {\tt driver} & string & the driver name \\ +\hline +\end{longtable} +\subsection{RPCs associated with class: PPCI} +\subsubsection{RPC name:~get\_all} + +{\bf Overview:} +Return a list of all the PPCIs known to the system. + + \noindent {\bf Signature:} +\begin{verbatim} ((PPCI ref) Set) get_all (session_id s)\end{verbatim} + + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +(PPCI ref) Set +} + + +references to all objects +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_uuid} + +{\bf Overview:} +Get the uuid field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_uuid (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_host} + +{\bf Overview:} +Get the host field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} (host ref) get_host (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +host ref +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_domain} + +{\bf Overview:} +Get the domain field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_domain (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_bus} + +{\bf Overview:} +Get the bus field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_bus (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_slot} + +{\bf Overview:} +Get the slot field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_slot (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_func} + +{\bf Overview:} +Get the func field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_func (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_name} + +{\bf Overview:} +Get the name field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_name (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_vendor\_id} + +{\bf Overview:} +Get the vendor\_id field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_vendor_id (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_vendor\_name} + +{\bf Overview:} +Get the vendor\_name field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_vendor_name (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_device\_id} + +{\bf Overview:} +Get the device\_id field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_device_id (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_device\_name} + +{\bf Overview:} +Get the device\_name field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_device_name (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_revision\_id} + +{\bf Overview:} +Get the revision\_id field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_revision_id (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_class\_code} + +{\bf Overview:} +Get the class\_code field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_class_code (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_class\_name} + +{\bf Overview:} +Get the class\_name field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_class_name (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_subsystem\_vendor\_id} + +{\bf Overview:} +Get the subsystem\_vendor\_id field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_subsystem_vendor_id (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_subsystem\_vendor\_name} + +{\bf Overview:} +Get the subsystem\_vendor\_name field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_subsystem_vendor_name (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_subsystem\_id} + +{\bf Overview:} +Get the subsystem\_id field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} int get_subsystem_id (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +int +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_subsystem\_name} + +{\bf Overview:} +Get the subsystem\_name field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_subsystem_name (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_driver} + +{\bf Overview:} +Get the driver field of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} string get_driver (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +string +} + + +value of the field +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_by\_uuid} + +{\bf Overview:} +Get a reference to the PPCI instance with the specified UUID. + + \noindent {\bf Signature:} +\begin{verbatim} (PPCI ref) get_by_uuid (session_id s, string uuid)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt string } & uuid & UUID of object to return \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +PPCI ref +} + + +reference to the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} +\subsubsection{RPC name:~get\_record} + +{\bf Overview:} +Get a record containing the current state of the given PPCI. + + \noindent {\bf Signature:} +\begin{verbatim} (PPCI record) get_record (session_id s, PPCI ref self)\end{verbatim} + + +\noindent{\bf Arguments:} + + +\vspace{0.3cm} +\begin{tabular}{|c|c|p{7cm}|} + \hline +{\bf type} & {\bf name} & {\bf description} \\ \hline +{\tt PPCI ref } & self & reference to the object \\ \hline + +\end{tabular} + +\vspace{0.3cm} + + \noindent {\bf Return Type:} +{\tt +PPCI record +} + + +all fields from the object +\vspace{0.3cm} +\vspace{0.3cm} +\vspace{0.3cm} + +\vspace{1cm} +\newpage \section{Class: user} \subsection{Fields for class: user} \begin{longtable}{|lllp{0.38\textwidth}|} diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/fs-front.c --- a/extras/mini-os/fs-front.c Thu Aug 07 11:47:34 2008 +0900 +++ b/extras/mini-os/fs-front.c Thu Aug 07 11:57:34 2008 +0900 @@ -50,6 +50,8 @@ struct fs_request; struct fs_import *fs_import; +void *alloc_buffer_page(struct fs_request *req, domid_t domid, grant_ref_t *gref); +void free_buffer_page(struct fs_request *req); /******************************************************************************/ /* RING REQUEST/RESPONSES HANDLING */ @@ -57,11 +59,19 @@ struct fs_import *fs_import; struct fs_request { - void *page; - grant_ref_t gref; + void *private1; /* Specific to request type */ + void *private2; struct thread *thread; /* Thread blocked on this request */ struct fsif_response shadow_rsp; /* Response copy writen by the interrupt handler */ +}; + +struct fs_rw_gnts +{ + /* TODO 16 bit? */ + int count; + grant_ref_t grefs[FSIF_NR_READ_GNTS]; + void *pages[FSIF_NR_READ_GNTS]; }; /* Ring operations: @@ -177,6 +187,8 @@ int fs_open(struct fs_import *import, ch { struct fs_request *fsr; unsigned short priv_req_id; + grant_ref_t gref; + void *buffer; RING_IDX back_req_id; struct fsif_request *req; int fd; @@ -189,14 +201,15 @@ int fs_open(struct fs_import *import, ch priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_open call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref id=%d\n", fsr->gref); - fsr->thread = current; - sprintf(fsr->page, "%s", file); + buffer = alloc_buffer_page(fsr, import->dom_id, &gref); + DEBUG("gref id=%d\n", gref); + fsr->thread = current; + sprintf(buffer, "%s", file); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_FILE_OPEN; req->id = priv_req_id; - req->u.fopen.gref = fsr->gref; + req->u.fopen.gref = gref; /* Set blocked flag before commiting the request, thus avoiding missed * response race */ @@ -207,6 +220,7 @@ int fs_open(struct fs_import *import, ch /* Read the response */ fd = (int)fsr->shadow_rsp.ret_val; DEBUG("The following FD returned: %d\n", fd); + free_buffer_page(fsr); add_id_to_freelist(priv_req_id, import->freelist); return fd; @@ -254,11 +268,13 @@ ssize_t fs_read(struct fs_import *import { struct fs_request *fsr; unsigned short priv_req_id; + struct fs_rw_gnts gnts; RING_IDX back_req_id; struct fsif_request *req; ssize_t ret; - - BUG_ON(len > PAGE_SIZE); + int i; + + BUG_ON(len > PAGE_SIZE * FSIF_NR_READ_GNTS); /* Prepare request for the backend */ back_req_id = reserve_fsif_request(import); @@ -268,17 +284,27 @@ ssize_t fs_read(struct fs_import *import priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_read call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - memset(fsr->page, 0, PAGE_SIZE); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_FILE_READ; req->id = priv_req_id; req->u.fread.fd = fd; - req->u.fread.gref = fsr->gref; req->u.fread.len = len; req->u.fread.offset = offset; + + + ASSERT(len > 0); + gnts.count = ((len - 1) / PAGE_SIZE) + 1; + for(i=0; i<gnts.count; i++) + { + gnts.pages[i] = (void *)alloc_page(); + gnts.grefs[i] = gnttab_grant_access(import->dom_id, + virt_to_mfn(gnts.pages[i]), + 0); + memset(gnts.pages[i], 0, PAGE_SIZE); + req->u.fread.grefs[i] = gnts.grefs[i]; + } + fsr->thread = current; /* Set blocked flag before commiting the request, thus avoiding missed * response race */ @@ -290,7 +316,19 @@ ssize_t fs_read(struct fs_import *import ret = (ssize_t)fsr->shadow_rsp.ret_val; DEBUG("The following ret value returned %d\n", ret); if(ret > 0) - memcpy(buf, fsr->page, ret); + { + ssize_t to_copy = ret, current_copy; + for(i=0; i<gnts.count; i++) + { + gnttab_end_access(gnts.grefs[i]); + current_copy = to_copy > PAGE_SIZE ? PAGE_SIZE : to_copy; + if(current_copy > 0) + memcpy(buf, gnts.pages[i], current_copy); + to_copy -= current_copy; + buf = (char*) buf + current_copy; + free_page(gnts.pages[i]); + } + } add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -301,11 +339,13 @@ ssize_t fs_write(struct fs_import *impor { struct fs_request *fsr; unsigned short priv_req_id; - RING_IDX back_req_id; - struct fsif_request *req; - ssize_t ret; - - BUG_ON(len > PAGE_SIZE); + struct fs_rw_gnts gnts; + RING_IDX back_req_id; + struct fsif_request *req; + ssize_t ret, to_copy; + int i; + + BUG_ON(len > PAGE_SIZE * FSIF_NR_WRITE_GNTS); /* Prepare request for the backend */ back_req_id = reserve_fsif_request(import); @@ -315,20 +355,35 @@ ssize_t fs_write(struct fs_import *impor priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_read call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - memcpy(fsr->page, buf, len); - BUG_ON(len > PAGE_SIZE); - memset((char *)fsr->page + len, 0, PAGE_SIZE - len); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_FILE_WRITE; req->id = priv_req_id; req->u.fwrite.fd = fd; - req->u.fwrite.gref = fsr->gref; req->u.fwrite.len = len; req->u.fwrite.offset = offset; + ASSERT(len > 0); + gnts.count = ((len - 1) / PAGE_SIZE) + 1; + to_copy = len; + for(i=0; i<gnts.count; i++) + { + int current_copy = (to_copy > PAGE_SIZE ? PAGE_SIZE : to_copy); + gnts.pages[i] = (void *)alloc_page(); + gnts.grefs[i] = gnttab_grant_access(import->dom_id, + virt_to_mfn(gnts.pages[i]), + 0); + memcpy(gnts.pages[i], buf, current_copy); + if(current_copy < PAGE_SIZE) + memset((char *)gnts.pages[i] + current_copy, + 0, + PAGE_SIZE - current_copy); + req->u.fwrite.grefs[i] = gnts.grefs[i]; + to_copy -= current_copy; + buf = (char*) buf + current_copy; + } + fsr->thread = current; + /* Set blocked flag before commiting the request, thus avoiding missed * response race */ block(current); @@ -338,6 +393,11 @@ ssize_t fs_write(struct fs_import *impor /* Read the response */ ret = (ssize_t)fsr->shadow_rsp.ret_val; DEBUG("The following ret value returned %d\n", ret); + for(i=0; i<gnts.count; i++) + { + gnttab_end_access(gnts.grefs[i]); + free_page(gnts.pages[i]); + } add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -361,15 +421,12 @@ int fs_stat(struct fs_import *import, priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_stat call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - memset(fsr->page, 0, PAGE_SIZE); + fsr->thread = current; req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_STAT; req->id = priv_req_id; req->u.fstat.fd = fd; - req->u.fstat.gref = fsr->gref; /* Set blocked flag before commiting the request, thus avoiding missed * response race */ @@ -380,7 +437,9 @@ int fs_stat(struct fs_import *import, /* Read the response */ ret = (int)fsr->shadow_rsp.ret_val; DEBUG("Following ret from fstat: %d\n", ret); - memcpy(stat, fsr->page, sizeof(struct fsif_stat_response)); + memcpy(stat, + &fsr->shadow_rsp.fstat, + sizeof(struct fsif_stat_response)); add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -430,6 +489,8 @@ int fs_remove(struct fs_import *import, { struct fs_request *fsr; unsigned short priv_req_id; + grant_ref_t gref; + void *buffer; RING_IDX back_req_id; struct fsif_request *req; int ret; @@ -442,14 +503,15 @@ int fs_remove(struct fs_import *import, priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_open call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - sprintf(fsr->page, "%s", file); + buffer = alloc_buffer_page(fsr, import->dom_id, &gref); + DEBUG("gref=%d\n", gref); + fsr->thread = current; + sprintf(buffer, "%s", file); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_REMOVE; req->id = priv_req_id; - req->u.fremove.gref = fsr->gref; + req->u.fremove.gref = gref; /* Set blocked flag before commiting the request, thus avoiding missed * response race */ @@ -460,6 +522,7 @@ int fs_remove(struct fs_import *import, /* Read the response */ ret = (int)fsr->shadow_rsp.ret_val; DEBUG("The following ret: %d\n", ret); + free_buffer_page(fsr); add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -472,6 +535,8 @@ int fs_rename(struct fs_import *import, { struct fs_request *fsr; unsigned short priv_req_id; + grant_ref_t gref; + void *buffer; RING_IDX back_req_id; struct fsif_request *req; int ret; @@ -486,15 +551,16 @@ int fs_rename(struct fs_import *import, priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_open call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - sprintf(fsr->page, "%s%s%c%s%s", + buffer = alloc_buffer_page(fsr, import->dom_id, &gref); + DEBUG("gref=%d\n", gref); + fsr->thread = current; + sprintf(buffer, "%s%s%c%s%s", old_header, old_file_name, '\0', new_header, new_file_name); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_RENAME; req->id = priv_req_id; - req->u.frename.gref = fsr->gref; + req->u.frename.gref = gref; req->u.frename.old_name_offset = strlen(old_header); req->u.frename.new_name_offset = strlen(old_header) + strlen(old_file_name) + @@ -511,6 +577,7 @@ int fs_rename(struct fs_import *import, /* Read the response */ ret = (int)fsr->shadow_rsp.ret_val; DEBUG("The following ret: %d\n", ret); + free_buffer_page(fsr); add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -521,6 +588,8 @@ int fs_create(struct fs_import *import, { struct fs_request *fsr; unsigned short priv_req_id; + grant_ref_t gref; + void *buffer; RING_IDX back_req_id; struct fsif_request *req; int ret; @@ -533,14 +602,15 @@ int fs_create(struct fs_import *import, priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_create call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - sprintf(fsr->page, "%s", name); + buffer = alloc_buffer_page(fsr, import->dom_id, &gref); + DEBUG("gref=%d\n", gref); + fsr->thread = current; + sprintf(buffer, "%s", name); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_CREATE; req->id = priv_req_id; - req->u.fcreate.gref = fsr->gref; + req->u.fcreate.gref = gref; req->u.fcreate.directory = directory; req->u.fcreate.mode = mode; @@ -553,6 +623,7 @@ int fs_create(struct fs_import *import, /* Read the response */ ret = (int)fsr->shadow_rsp.ret_val; DEBUG("The following ret: %d\n", ret); + free_buffer_page(fsr); add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -563,6 +634,8 @@ char** fs_list(struct fs_import *import, { struct fs_request *fsr; unsigned short priv_req_id; + grant_ref_t gref; + void *buffer; RING_IDX back_req_id; struct fsif_request *req; char **files, *current_file; @@ -579,14 +652,15 @@ char** fs_list(struct fs_import *import, priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_list call is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - sprintf(fsr->page, "%s", name); + buffer = alloc_buffer_page(fsr, import->dom_id, &gref); + DEBUG("gref=%d\n", gref); + fsr->thread = current; + sprintf(buffer, "%s", name); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_DIR_LIST; req->id = priv_req_id; - req->u.flist.gref = fsr->gref; + req->u.flist.gref = gref; req->u.flist.offset = offset; /* Set blocked flag before commiting the request, thus avoiding missed @@ -600,7 +674,7 @@ char** fs_list(struct fs_import *import, files = NULL; if(*nr_files <= 0) goto exit; files = malloc(sizeof(char*) * (*nr_files)); - current_file = fsr->page; + current_file = buffer; for(i=0; i<*nr_files; i++) { files[i] = strdup(current_file); @@ -608,6 +682,7 @@ char** fs_list(struct fs_import *import, } if(has_more != NULL) *has_more = fsr->shadow_rsp.ret_val & HAS_MORE_FLAG; + free_buffer_page(fsr); add_id_to_freelist(priv_req_id, import->freelist); exit: return files; @@ -655,6 +730,8 @@ int64_t fs_space(struct fs_import *impor { struct fs_request *fsr; unsigned short priv_req_id; + grant_ref_t gref; + void *buffer; RING_IDX back_req_id; struct fsif_request *req; int64_t ret; @@ -667,14 +744,15 @@ int64_t fs_space(struct fs_import *impor priv_req_id = get_id_from_freelist(import->freelist); DEBUG("Request id for fs_space is: %d\n", priv_req_id); fsr = &import->requests[priv_req_id]; - DEBUG("gref=%d\n", fsr->gref); - fsr->thread = current; - sprintf(fsr->page, "%s", location); + buffer = alloc_buffer_page(fsr, import->dom_id, &gref); + DEBUG("gref=%d\n", gref); + fsr->thread = current; + sprintf(buffer, "%s", location); req = RING_GET_REQUEST(&import->ring, back_req_id); req->type = REQ_FS_SPACE; req->id = priv_req_id; - req->u.fspace.gref = fsr->gref; + req->u.fspace.gref = gref; /* Set blocked flag before commiting the request, thus avoiding missed * response race */ @@ -685,6 +763,7 @@ int64_t fs_space(struct fs_import *impor /* Read the response */ ret = (int64_t)fsr->shadow_rsp.ret_val; DEBUG("The following returned: %lld\n", ret); + free_buffer_page(fsr); add_id_to_freelist(priv_req_id, import->freelist); return ret; @@ -732,6 +811,23 @@ int fs_sync(struct fs_import *import, in /* END OF INDIVIDUAL FILE OPERATIONS */ /******************************************************************************/ +void *alloc_buffer_page(struct fs_request *req, domid_t domid, grant_ref_t *gref) +{ + void *page; + + page = (void *)alloc_page(); + *gref = gnttab_grant_access(domid, virt_to_mfn(page), 0); + req->private1 = page; + req->private2 = (void *)(uintptr_t)(*gref); + + return page; +} + +void free_buffer_page(struct fs_request *req) +{ + gnttab_end_access((grant_ref_t)(uintptr_t)req->private2); + free_page(req->private1); +} static void fsfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) { @@ -797,15 +893,7 @@ static void alloc_request_table(struct f import->freelist = xmalloc_array(unsigned short, import->nr_entries + 1); memset(import->freelist, 0, sizeof(unsigned short) * (import->nr_entries + 1)); for(i=0; i<import->nr_entries; i++) - { - /* TODO: that's a lot of memory */ - requests[i].page = (void *)alloc_page(); - requests[i].gref = gnttab_grant_access(import->dom_id, - virt_to_mfn(requests[i].page), - 0); - //printk(" ===>> Page=%lx, gref=%d, mfn=%lx\n", requests[i].page, requests[i].gref, virt_to_mfn(requests[i].page)); add_id_to_freelist(i, import->freelist); - } import->requests = requests; } @@ -818,22 +906,27 @@ void test_fs_import(void *data) void test_fs_import(void *data) { struct fs_import *import = (struct fs_import *)data; - int ret, fd, i; + int ret, fd, i, repeat_count; int32_t nr_files; char buffer[1024]; ssize_t offset; char **files; long ret64; - + struct fsif_stat_response stat; + + repeat_count = 10; /* Sleep for 1s and then try to open a file */ msleep(1000); +again: ret = fs_create(import, "mini-os-created-directory", 1, 0777); printk("Directory create: %d\n", ret); - ret = fs_create(import, "mini-os-created-directory/mini-os-created-file", 0, 0666); + sprintf(buffer, "mini-os-created-directory/mini-os-created-file-%d", + repeat_count); + ret = fs_create(import, buffer, 0, 0666); printk("File create: %d\n", ret); - fd = fs_open(import, "mini-os-created-directory/mini-os-created-file"); + fd = fs_open(import, buffer); printk("File descriptor: %d\n", fd); if(fd < 0) return; @@ -847,7 +940,16 @@ void test_fs_import(void *data) return; offset += ret; } - + ret = fs_stat(import, fd, &stat); + printk("Ret after stat: %d\n", ret); + printk(" st_mode=%o\n", stat.stat_mode); + printk(" st_uid =%d\n", stat.stat_uid); + printk(" st_gid =%d\n", stat.stat_gid); + printk(" st_size=%ld\n", stat.stat_size); + printk(" st_atime=%ld\n", stat.stat_atime); + printk(" st_mtime=%ld\n", stat.stat_mtime); + printk(" st_ctime=%ld\n", stat.stat_ctime); + ret = fs_close(import, fd); printk("Closed fd: %d, ret=%d\n", fd, ret); @@ -858,6 +960,9 @@ void test_fs_import(void *data) ret64 = fs_space(import, "/"); printk("Free space: %lld (=%lld Mb)\n", ret64, (ret64 >> 20)); + repeat_count--; + if(repeat_count > 0) + goto again; } @@ -924,20 +1029,21 @@ static int init_fs_import(struct fs_impo xenbus_transaction_t xbt; char nodename[1024], r_nodename[1024], token[128], *message = NULL; struct fsif_sring *sring; - int retry = 0; + int i, retry = 0; domid_t self_id; xenbus_event_queue events = NULL; printk("Initialising FS fortend to backend dom %d\n", import->dom_id); /* Allocate page for the shared ring */ - sring = (struct fsif_sring*) alloc_page(); - memset(sring, 0, PAGE_SIZE); + sring = (struct fsif_sring*) alloc_pages(FSIF_RING_SIZE_ORDER); + memset(sring, 0, PAGE_SIZE * FSIF_RING_SIZE_PAGES); /* Init the shared ring */ SHARED_RING_INIT(sring); + ASSERT(FSIF_NR_READ_GNTS == FSIF_NR_WRITE_GNTS); /* Init private frontend ring */ - FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE); + FRONT_RING_INIT(&import->ring, sring, PAGE_SIZE * FSIF_RING_SIZE_PAGES); import->nr_entries = import->ring.nr_ents; /* Allocate table of requests */ @@ -945,7 +1051,11 @@ static int init_fs_import(struct fs_impo init_SEMAPHORE(&import->reqs_sem, import->nr_entries); /* Grant access to the shared ring */ - import->gnt_ref = gnttab_grant_access(import->dom_id, virt_to_mfn(sring), 0); + for(i=0; i<FSIF_RING_SIZE_PAGES; i++) + import->gnt_refs[i] = + gnttab_grant_access(import->dom_id, + virt_to_mfn((char *)sring + i * PAGE_SIZE), + 0); /* Allocate event channel */ BUG_ON(evtchn_alloc_unbound(import->dom_id, @@ -969,12 +1079,26 @@ again: err = xenbus_printf(xbt, nodename, - "ring-ref", + "ring-size", "%u", - import->gnt_ref); + FSIF_RING_SIZE_PAGES); if (err) { - message = "writing ring-ref"; + message = "writing ring-size"; goto abort_transaction; + } + + for(i=0; i<FSIF_RING_SIZE_PAGES; i++) + { + sprintf(r_nodename, "ring-ref-%d", i); + err = xenbus_printf(xbt, + nodename, + r_nodename, + "%u", + import->gnt_refs[i]); + if (err) { + message = "writing ring-refs"; + goto abort_transaction; + } } err = xenbus_printf(xbt, diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/gntmap.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/gntmap.c Thu Aug 07 11:57:34 2008 +0900 @@ -0,0 +1,252 @@ +/* + * Manages grant mappings from other domains. + * + * Diego Ongaro <diego.ongaro@xxxxxxxxxx>, July 2008 + * + * Files of type FTYPE_GNTMAP contain a gntmap, which is an array of + * (host address, grant handle) pairs. Grant handles come from a hypervisor map + * operation and are needed for the corresponding unmap. + * + * This is a rather naive implementation in terms of performance. If we start + * using it frequently, there's definitely some low-hanging fruit here. + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <os.h> +#include <xmalloc.h> +#include <errno.h> +#include <xen/grant_table.h> +#include <inttypes.h> +#include "gntmap.h" + +#define DEFAULT_MAX_GRANTS 128 + +struct gntmap_entry { + unsigned long host_addr; + grant_handle_t handle; +}; + +static inline int +gntmap_entry_used(struct gntmap_entry *entry) +{ + return entry->host_addr != 0; +} + +static struct gntmap_entry* +gntmap_find_free_entry(struct gntmap *map) +{ + int i; + + for (i = 0; i < map->nentries; i++) { + if (!gntmap_entry_used(&map->entries[i])) + return &map->entries[i]; + } + +#ifdef GNTMAP_DEBUG + printk("gntmap_find_free_entry(map=%p): all %d entries full\n", + map, map->nentries); +#endif + return NULL; +} + +static struct gntmap_entry* +gntmap_find_entry(struct gntmap *map, unsigned long addr) +{ + int i; + + for (i = 0; i < map->nentries; i++) { + if (map->entries[i].host_addr == addr) + return &map->entries[i]; + } + return NULL; +} + +int +gntmap_set_max_grants(struct gntmap *map, int count) +{ +#ifdef GNTMAP_DEBUG + printk("gntmap_set_max_grants(map=%p, count=%d)\n", map, count); +#endif + + if (map->nentries != 0) + return -EBUSY; + + map->entries = xmalloc_array(struct gntmap_entry, count); + if (map->entries == NULL) + return -ENOMEM; + + memset(map->entries, 0, sizeof(struct gntmap_entry) * count); + map->nentries = count; + return 0; +} + +static int +_gntmap_map_grant_ref(struct gntmap_entry *entry, + unsigned long host_addr, + uint32_t domid, + uint32_t ref, + int writable) +{ + struct gnttab_map_grant_ref op; + int rc; + + op.ref = (grant_ref_t) ref; + op.dom = (domid_t) domid; + op.host_addr = (uint64_t) host_addr; + op.flags = GNTMAP_host_map; + if (!writable) + op.flags |= GNTMAP_readonly; + + rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1); + if (rc != 0 || op.status != GNTST_okay) { + printk("GNTTABOP_map_grant_ref failed: " + "returned %d, status %" PRId16 "\n", + rc, op.status); + return rc != 0 ? rc : op.status; + } + + entry->host_addr = host_addr; + entry->handle = op.handle; + return 0; +} + +static int +_gntmap_unmap_grant_ref(struct gntmap_entry *entry) +{ + struct gnttab_unmap_grant_ref op; + int rc; + + op.host_addr = (uint64_t) entry->host_addr; + op.dev_bus_addr = 0; + op.handle = entry->handle; + + rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1); + if (rc != 0 || op.status != GNTST_okay) { + printk("GNTTABOP_unmap_grant_ref failed: " + "returned %d, status %" PRId16 "\n", + rc, op.status); + return rc != 0 ? rc : op.status; + } + + entry->host_addr = 0; + return 0; +} + +int +gntmap_munmap(struct gntmap *map, unsigned long start_address, int count) +{ + int i, rc; + struct gntmap_entry *ent; + +#ifdef GNTMAP_DEBUG + printk("gntmap_munmap(map=%p, start_address=%lx, count=%d)\n", + map, start_address, count); +#endif + + for (i = 0; i < count; i++) { + ent = gntmap_find_entry(map, start_address + PAGE_SIZE * i); + if (ent == NULL) { + printk("gntmap: tried to munmap unknown page\n"); + return -EINVAL; + } + + rc = _gntmap_unmap_grant_ref(ent); + if (rc != 0) + return rc; + } + + return 0; +} + +void* +gntmap_map_grant_refs(struct gntmap *map, + uint32_t count, + uint32_t *domids, + int domids_stride, + uint32_t *refs, + int writable) +{ + unsigned long addr; + struct gntmap_entry *ent; + int i; + +#ifdef GNTMAP_DEBUG + printk("gntmap_map_grant_refs(map=%p, count=%" PRIu32 ", " + "domids=%p [%" PRIu32 "...], domids_stride=%d, " + "refs=%p [%" PRIu32 "...], writable=%d)\n", + map, count, + domids, domids == NULL ? 0 : domids[0], domids_stride, + refs, refs == NULL ? 0 : refs[0], writable); +#endif + + (void) gntmap_set_max_grants(map, DEFAULT_MAX_GRANTS); + + addr = allocate_ondemand((unsigned long) count, 1); + if (addr == 0) + return NULL; + + for (i = 0; i < count; i++) { + ent = gntmap_find_free_entry(map); + if (ent == NULL || + _gntmap_map_grant_ref(ent, + addr + PAGE_SIZE * i, + domids[i * domids_stride], + refs[i], + writable) != 0) { + + (void) gntmap_munmap(map, addr, i); + return NULL; + } + } + + return (void*) addr; +} + +void +gntmap_init(struct gntmap *map) +{ +#ifdef GNTMAP_DEBUG + printk("gntmap_init(map=%p)\n", map); +#endif + map->nentries = 0; + map->entries = NULL; +} + +void +gntmap_fini(struct gntmap *map) +{ + struct gntmap_entry *ent; + int i; + +#ifdef GNTMAP_DEBUG + printk("gntmap_fini(map=%p)\n", map); +#endif + + for (i = 0; i < map->nentries; i++) { + ent = &map->entries[i]; + if (gntmap_entry_used(ent)) + (void) _gntmap_unmap_grant_ref(ent); + } + + xfree(map->entries); + map->entries = NULL; + map->nentries = 0; +} diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/include/fs.h --- a/extras/mini-os/include/fs.h Thu Aug 07 11:47:34 2008 +0900 +++ b/extras/mini-os/include/fs.h Thu Aug 07 11:57:34 2008 +0900 @@ -4,6 +4,9 @@ #include <xen/io/fsif.h> #include <mini-os/semaphore.h> #include <mini-os/types.h> + +#define FSIF_RING_SIZE_ORDER 1 +#define FSIF_RING_SIZE_PAGES (1<<FSIF_RING_SIZE_ORDER) struct fs_import { @@ -14,7 +17,7 @@ struct fs_import unsigned int nr_entries; /* Number of entries in rings & request array */ struct fsif_front_ring ring; /* frontend ring (contains shared ring) */ - int gnt_ref; /* grant reference to the shared ring */ + u32 gnt_refs[FSIF_RING_SIZE_PAGES]; /* grant references to the shared ring */ evtchn_port_t local_port; /* local event channel port */ char *backend; /* XenBus location of the backend */ struct fs_request *requests; /* Table of requests */ diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/include/gntmap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/mini-os/include/gntmap.h Thu Aug 07 11:57:34 2008 +0900 @@ -0,0 +1,35 @@ +#ifndef __GNTMAP_H__ +#define __GNTMAP_H__ + +#include <os.h> + +/* + * Please consider struct gntmap opaque. If instead you choose to disregard + * this message, I insist that you keep an eye out for raptors. + */ +struct gntmap { + int nentries; + struct gntmap_entry *entries; +}; + +int +gntmap_set_max_grants(struct gntmap *map, int count); + +int +gntmap_munmap(struct gntmap *map, unsigned long start_address, int count); + +void* +gntmap_map_grant_refs(struct gntmap *map, + uint32_t count, + uint32_t *domids, + int domids_stride, + uint32_t *refs, + int writable); + +void +gntmap_init(struct gntmap *map); + +void +gntmap_fini(struct gntmap *map); + +#endif /* !__GNTMAP_H__ */ diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/include/lib.h --- a/extras/mini-os/include/lib.h Thu Aug 07 11:47:34 2008 +0900 +++ b/extras/mini-os/include/lib.h Thu Aug 07 11:57:34 2008 +0900 @@ -59,6 +59,7 @@ #include <stddef.h> #include <xen/xen.h> #include <xen/event_channel.h> +#include "gntmap.h" #ifdef HAVE_LIBC #include <stdio.h> @@ -138,6 +139,7 @@ enum fd_type { FTYPE_XENBUS, FTYPE_XC, FTYPE_EVTCHN, + FTYPE_GNTMAP, FTYPE_SOCKET, FTYPE_TAP, FTYPE_BLK, @@ -168,6 +170,7 @@ extern struct file { int bound; } ports[MAX_EVTCHN_PORTS]; } evtchn; + struct gntmap gntmap; struct { struct netfront_dev *dev; } tap; diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/lib/sys.c --- a/extras/mini-os/lib/sys.c Thu Aug 07 11:47:34 2008 +0900 +++ b/extras/mini-os/lib/sys.c Thu Aug 07 11:57:34 2008 +0900 @@ -84,6 +84,7 @@ #define NOFILE 32 extern int xc_evtchn_close(int fd); extern int xc_interface_close(int fd); +extern int xc_gnttab_close(int fd); pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER; struct file files[NOFILE] = { @@ -230,8 +231,8 @@ int read(int fd, void *buf, size_t nbyte } case FTYPE_FILE: { ssize_t ret; - if (nbytes > PAGE_SIZE) - nbytes = PAGE_SIZE; + if (nbytes > PAGE_SIZE * FSIF_NR_READ_GNTS) + nbytes = PAGE_SIZE * FSIF_NR_READ_GNTS; ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, files[fd].file.offset); if (ret > 0) { files[fd].file.offset += ret; @@ -291,8 +292,8 @@ int write(int fd, const void *buf, size_ return nbytes; case FTYPE_FILE: { ssize_t ret; - if (nbytes > PAGE_SIZE) - nbytes = PAGE_SIZE; + if (nbytes > PAGE_SIZE * FSIF_NR_WRITE_GNTS) + nbytes = PAGE_SIZE * FSIF_NR_WRITE_GNTS; ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, files[fd].file.offset); if (ret > 0) { files[fd].file.offset += ret; @@ -401,6 +402,9 @@ int close(int fd) case FTYPE_EVTCHN: xc_evtchn_close(fd); return 0; + case FTYPE_GNTMAP: + xc_gnttab_close(fd); + return 0; case FTYPE_TAP: shutdown_netfront(files[fd].tap.dev); files[fd].type = FTYPE_NONE; diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/minios.mk --- a/extras/mini-os/minios.mk Thu Aug 07 11:47:34 2008 +0900 +++ b/extras/mini-os/minios.mk Thu Aug 07 11:57:34 2008 +0900 @@ -21,6 +21,7 @@ DEF_CFLAGS += -g #DEF_CFLAGS += -DFS_DEBUG #DEF_CFLAGS += -DLIBC_DEBUG DEF_CFLAGS += -DGNT_DEBUG +DEF_CFLAGS += -DGNTMAP_DEBUG else DEF_CFLAGS += -O3 endif diff -r 7affdebb7a1e -r a39913db6e51 extras/mini-os/pcifront.c --- a/extras/mini-os/pcifront.c Thu Aug 07 11:47:34 2008 +0900 +++ b/extras/mini-os/pcifront.c Thu Aug 07 11:57:34 2008 +0900 @@ -57,19 +57,26 @@ struct pcifront_dev *init_pcifront(char int retry=0; char* msg; char* nodename = _nodename ? _nodename : "device/pci/0"; + int dom; struct pcifront_dev *dev; char path[strlen(nodename) + 1 + 10 + 1]; printk("******************* PCIFRONT for %s **********\n\n\n", nodename); + + snprintf(path, sizeof(path), "%s/backend-id", nodename); + dom = xenbus_read_integer(path); + if (dom == -1) { + printk("no backend\n"); + return NULL; + } dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); - - snprintf(path, sizeof(path), "%s/backend-id", nodename); - dev->dom = xenbus_read_integer(path); + dev->dom = dom; + evtchn_alloc_unbound(dev->dom, pcifront_handler, dev, &dev->evtchn); dev->info = (struct xen_pci_sharedinfo*) alloc_page(); diff -r 7affdebb7a1e -r a39913db6e51 stubdom/Makefile --- a/stubdom/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/stubdom/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -2,18 +2,23 @@ MINI_OS = $(XEN_ROOT)/extras/mini-os MINI_OS = $(XEN_ROOT)/extras/mini-os export XEN_OS=MiniOS - -CONFIG_QEMU=ioemu export stubdom=y export debug=y include $(XEN_ROOT)/Config.mk +override CONFIG_QEMU=ioemu + IOEMU_OPTIONS=--disable-sdl --disable-opengl --disable-gfx-check --disable-vnc-tls --disable-brlapi --disable-kqemu +ZLIB_URL?=http://www.zlib.net ZLIB_VERSION=1.2.3 +LIBPCI_URL?=http://www.kernel.org/pub/software/utils/pciutils LIBPCI_VERSION=2.2.9 +NEWLIB_URL?=ftp://sources.redhat.com/pub/newlib NEWLIB_VERSION=1.16.0 +LWIP_URL?=http://download.savannah.gnu.org/releases/lwip LWIP_VERSION=1.3.0 +GRUB_URL?=http://alpha.gnu.org/gnu/grub GRUB_VERSION=0.97 WGET=wget -c @@ -75,7 +80,7 @@ endif ############## newlib-$(NEWLIB_VERSION).tar.gz: - $(WGET) ftp://sources.redhat.com/pub/newlib/$@ + $(WGET) $(NEWLIB_URL)/$@ newlib-$(NEWLIB_VERSION): newlib-$(NEWLIB_VERSION).tar.gz tar xzf $< @@ -97,7 +102,7 @@ cross-newlib: $(NEWLIB_STAMPFILE) ############ zlib-$(ZLIB_VERSION).tar.gz: - $(WGET) http://www.zlib.net/$@ + $(WGET) $(ZLIB_URL)/$@ ZLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libz.a .PHONY: cross-zlib @@ -114,7 +119,7 @@ cross-zlib: $(ZLIB_STAMPFILE) ############## pciutils-$(LIBPCI_VERSION).tar.bz2: - $(WGET) http://www.kernel.org/pub/software/utils/pciutils/$@ + $(WGET) $(LIBPCI_URL)/$@ pciutils-$(LIBPCI_VERSION): pciutils-$(LIBPCI_VERSION).tar.bz2 tar xjf $< @@ -132,7 +137,7 @@ cross-libpci: $(LIBPCI_STAMPFILE) $(MAKE) CC="$(CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -I$(realpath $(MINI_OS)/include)" lib/libpci.a && \ $(INSTALL_DATA) lib/libpci.a $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ && \ $(INSTALL_DIR) $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci && \ - $(INSTALL_DATA) lib/{config,header,pci,types}.h $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \ + $(INSTALL_DATA) lib/config.h lib/header.h lib/pci.h lib/types.h $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \ ) ###### @@ -140,7 +145,7 @@ cross-libpci: $(LIBPCI_STAMPFILE) ###### lwip-$(LWIP_VERSION).tar.gz: - $(WGET) http://download.savannah.gnu.org/releases/lwip/$@ + $(WGET) $(LWIP_URL)/$@ lwip: lwip-$(LWIP_VERSION).tar.gz tar xzf $< @@ -154,7 +159,6 @@ lwip: lwip-$(LWIP_VERSION).tar.gz .PHONY: $(CROSS_ROOT) $(CROSS_ROOT): cross-newlib cross-zlib cross-libpci -.PHONY: mk-headers mk-headers: mkdir -p include/xen && \ ln -sf $(addprefix ../../,$(wildcard $(XEN_ROOT)/xen/include/public/*.h)) include/xen && \ @@ -191,6 +195,7 @@ endif [ ! -h ioemu/config-host.h ] || rm -f ioemu/config-host.h [ ! -h ioemu/config-host.mak ] || rm -f ioemu/config-host.mak $(MAKE) -C $(MINI_OS) links + touch mk-headers TARGETS_MINIOS=$(addprefix mini-os-,$(TARGETS)) $(TARGETS_MINIOS): mini-os-%: @@ -247,7 +252,7 @@ c: $(CROSS_ROOT) ###### grub-$(GRUB_VERSION).tar.gz: - $(WGET) ftp://alpha.gnu.org/gnu/grub/$@ + $(WGET) $(GRUB_URL)/$@ grub-upstream: grub-$(GRUB_VERSION).tar.gz tar xzf $< @@ -291,20 +296,24 @@ pv-grub: mini-os-grub libxc grub ######### ifeq ($(STUBDOM_SUPPORTED),1) -install: install-ioemu install-grub +install: install-readme install-ioemu install-grub else install: endif + +install-readme: + $(INSTALL_DIR) $(DESTDIR)$(DOCDIR) + $(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.stubdom install-ioemu: ioemu-stubdom $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/bin" $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin" $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot" - $(INSTALL_PROG) mini-os-ioemu/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/ioemu-stubdom.gz" + $(INSTALL_DATA) mini-os-ioemu/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/ioemu-stubdom.gz" install-grub: pv-grub $(INSTALL_DIR) "$(DESTDIR)/usr/lib/xen/boot" - $(INSTALL_PROG) mini-os-grub/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/pv-grub.gz" + $(INSTALL_DATA) mini-os-grub/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/pv-grub.gz" ####### # clean @@ -320,7 +329,8 @@ clean: $(MAKE) -C caml clean $(MAKE) -C c clean $(MAKE) -C grub clean - rm -fr libxc ioemu mini-os include + [ ! -d libxc ] || $(MAKE) -C libxc clean + [ ! -d ioemu ] || $(MAKE) -C ioemu clean # clean the cross-compilation result .PHONY: crossclean @@ -328,6 +338,8 @@ crossclean: clean rm -fr $(CROSS_ROOT) rm -fr newlib-build rm -fr zlib-$(ZLIB_VERSION) pciutils-$(LIBPCI_VERSION) + rm -fr libxc ioemu + rm -f mk-headers # clean patched sources .PHONY: patchclean diff -r 7affdebb7a1e -r a39913db6e51 stubdom/README --- a/stubdom/README Thu Aug 07 11:47:34 2008 +0900 +++ b/stubdom/README Thu Aug 07 11:57:34 2008 +0900 @@ -1,13 +1,3 @@ To compile -To compile -========== - -Just run make -j 4, that will download / patch / compile -Then make install to install the result. - -Also, run make and make install in $XEN_ROOT/tools/fs-back - - - IOEMU stubdom ============= @@ -15,6 +5,14 @@ Also, run make and make install in $XEN_ General Configuration ===================== + +Due to a race between the creation of the IOEMU stubdomain itself and allocation +of video memory for the HVM domain, you need to avoid the need for ballooning, +by using the hypervisor dom0_mem= option for instance. + + +There is a sample configuration set in xmexample.hvm-stubdom and +xmexample.hvm-dm In your HVM config "hvmconfig", diff -r 7affdebb7a1e -r a39913db6e51 stubdom/stubdom-dm --- a/stubdom/stubdom-dm Thu Aug 07 11:47:34 2008 +0900 +++ b/stubdom/stubdom-dm Thu Aug 07 11:57:34 2008 +0900 @@ -55,7 +55,7 @@ term() { kill %1 ( [ -n "$vncpid" ] && kill -9 $vncpid - xm destroy stubdom-$domname + xm destroy $domname-dm #xm destroy $domname ) & # We need to exit immediately so as to let xend do the commands above @@ -67,12 +67,12 @@ trap term SIGHUP ############ # stubdomain # Wait for any previous stubdom to terminate -while xm list | grep stubdom-$domname +while xm list | grep $domname-dm do sleep 1 done -creation="xm create -c stubdom-$domname target=$domid memory=32 extra=\"$extra\"" +creation="xm create -c $domname-dm target=$domid memory=32 extra=\"$extra\"" (while true ; do sleep 60 ; done) | /bin/sh -c "$creation" & #xterm -geometry +0+0 -e /bin/sh -c "$creation ; echo ; echo press ENTER to shut down ; read" & diff -r 7affdebb7a1e -r a39913db6e51 tools/Makefile --- a/tools/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -55,13 +55,14 @@ clean distclean: subdirs-clean clean distclean: subdirs-clean ifneq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH)) -IOEMU_CONFIGURE_CROSS ?= --cross-prefix=$(CROSS_COMPILE) \ +IOEMU_CONFIGURE_CROSS ?= --cpu=$(XEN_TARGET_ARCH) \ + --cross-prefix=$(CROSS_COMPILE) \ --interp-prefix=$(CROSS_SYS_ROOT) endif ioemu/config-host.mak: - cd ioemu && XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) sh configure --prefix=/usr \ - $(IOEMU_CONFIGURE_CROSS) + cd ioemu && XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) sh configure \ + --prefix=$(PREFIX) $(IOEMU_CONFIGURE_CROSS) subdir-all-ioemu subdir-install-ioemu: ioemu/config-host.mak @@ -78,6 +79,12 @@ ioemu-dir-find: rm -rf ioemu-remote ioemu-remote.tmp; \ mkdir ioemu-remote.tmp; rmdir ioemu-remote.tmp; \ $(GIT) clone $(CONFIG_QEMU) ioemu-remote.tmp; \ + if [ "$(QEMU_TAG)" ]; then \ + cd ioemu-remote.tmp; \ + $(GIT) branch -D dummy >/dev/null 2>&1 ||:; \ + $(GIT) checkout -b dummy $(QEMU_TAG); \ + cd ..; \ + fi; \ mv ioemu-remote.tmp ioemu-remote; \ fi; \ rm -f ioemu-dir; \ @@ -90,7 +97,7 @@ ioemu-dir-find: esac; \ export XEN_ROOT; \ cd ioemu-dir; \ - ./xen-setup + ./xen-setup $(IOEMU_CONFIGURE_CROSS) subdir-all-ioemu-dir subdir-install-ioemu-dir: ioemu-dir-find diff -r 7affdebb7a1e -r a39913db6e51 tools/blktap/Makefile --- a/tools/blktap/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/blktap/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -8,3 +8,6 @@ SUBDIRS-y += drivers .PHONY: all clean install all clean install: %: subdirs-% +install: + $(INSTALL_DIR) $(DESTDIR)$(DOCDIR) + $(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.blktap diff -r 7affdebb7a1e -r a39913db6e51 tools/blktap/lib/Makefile --- a/tools/blktap/lib/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/blktap/lib/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -43,7 +43,7 @@ install: all .PHONY: clean clean: - rm -rf *.a *.so* *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS + rm -rf *.a *.so* *.o *.opic *.rpm $(LIB) *~ $(DEPS) xen TAGS libblktap.so.$(MAJOR).$(MINOR): $(OBJS_PIC) $(CC) $(CFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,$(SONAME) $(SHLIB_CFLAGS) \ diff -r 7affdebb7a1e -r a39913db6e51 tools/console/Makefile --- a/tools/console/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/console/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -21,7 +21,7 @@ clean: xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c)) $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) \ - $(UTIL_LIBS) $(SOCKET_LIBS) + $(UTIL_LIBS) $(SOCKET_LIBS) -lrt xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c)) $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) \ diff -r 7affdebb7a1e -r a39913db6e51 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/console/daemon/io.c Thu Aug 07 11:57:34 2008 +0900 @@ -622,9 +622,9 @@ static struct domain *create_domain(int { struct domain *dom; char *s; - struct timeval tv; - - if (gettimeofday(&tv, NULL) < 0) { + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) { dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d", __FILE__, __FUNCTION__, __LINE__); return NULL; @@ -666,7 +666,7 @@ static struct domain *create_domain(int dom->buffer.capacity = 0; dom->buffer.max_capacity = 0; dom->event_count = 0; - dom->next_period = (tv.tv_sec * 1000) + (tv.tv_usec / 1000) + RATE_LIMIT_PERIOD; + dom->next_period = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000) + RATE_LIMIT_PERIOD; dom->next = NULL; dom->ring_ref = -1; @@ -971,7 +971,7 @@ void handle_io(void) struct domain *d, *n; int max_fd = -1; struct timeval timeout; - struct timeval tv; + struct timespec ts; long long now, next_timeout = 0; FD_ZERO(&readfds); @@ -985,9 +985,9 @@ void handle_io(void) max_fd = MAX(xc_evtchn_fd(xce_handle), max_fd); } - if (gettimeofday(&tv, NULL) < 0) + if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) return; - now = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + now = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000); /* Re-calculate any event counter allowances & unblock domains with new allowance */ diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/Makefile --- a/tools/examples/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -8,11 +8,18 @@ XENDOMAINS_SYSCONFIG = init.d/sysconfig. # Xen configuration dir and configs to go there. XEN_CONFIG_DIR = /etc/xen +XEN_READMES = README +XEN_READMES += README.incompatibilities XEN_CONFIGS = xend-config.sxp XEN_CONFIGS += xm-config.xml XEN_CONFIGS += xmexample1 XEN_CONFIGS += xmexample2 +XEN_CONFIGS += xmexample3 XEN_CONFIGS += xmexample.hvm +XEN_CONFIGS += xmexample.hvm-stubdom +XEN_CONFIGS += xmexample.hvm-dm +XEN_CONFIGS += xmexample.pv-grub +XEN_CONFIGS += xmexample.nbd XEN_CONFIGS += xmexample.vti XEN_CONFIGS += xend-pci-quirks.sxp XEN_CONFIGS += xend-pci-permissive.sxp @@ -59,7 +66,16 @@ build: build: .PHONY: install -install: all install-initd install-configs install-scripts $(HOTPLUGS) +install: all install-readmes install-initd install-configs install-scripts $(HOTPLUGS) + +.PHONY: install-readmes +install-readmes: + [ -d $(DESTDIR)$(XEN_CONFIG_DIR) ] || \ + $(INSTALL_DIR) $(DESTDIR)$(XEN_CONFIG_DIR) + set -e; for i in $(XEN_READMES); \ + do [ -e $(DESTDIR)$(XEN_CONFIG_DIR)/$$i ] || \ + $(INSTALL_DATA) $$i $(DESTDIR)$(XEN_CONFIG_DIR); \ + done .PHONY: install-initd install-initd: diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/README --- a/tools/examples/README Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/README Thu Aug 07 11:57:34 2008 +0900 @@ -44,4 +44,8 @@ xmexample.nbd - configuration scri xmexample.nbd - configuration script that uses NBD filesystems xmexample.hvm - a configuration script for creating a hvm domain with 'xm create' +xmexample.hvm-stubdom - a configuration script for creating a hvm domain with + 'xm create' that utilizes a stubdomain for device model +xmexample.pv-grub - a configuration script for creating a domain with 'xm create' + which boots PV-GRUB. xmexample.vti - a configuration script for creating a domain on vti diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/stubdom-ExampleHVMDomain --- a/tools/examples/stubdom-ExampleHVMDomain Thu Aug 07 11:47:34 2008 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -# Not to be started directly, -# See xmexample.hvm-stubdom and stubdom/README for more details - -kernel = "/usr/lib/xen/boot/ioemu-stubdom.gz" - -# Must be the same as in xmexample.hvm-stubdom, with a prepended vif for TCP/IP -# networking in the stubdomain itself, here just '' -vif = [ '', 'type=ioemu, bridge=xenbr0' ] - -# Set here instead of in xmexample.hvm-stubdom -disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ] - -# Actual output via PVFB -vfb = [ 'type=sdl' ] diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xend-config.sxp --- a/tools/examples/xend-config.sxp Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/xend-config.sxp Thu Aug 07 11:57:34 2008 +0900 @@ -245,3 +245,7 @@ # Rotation count of qemu-dm log file. #(qemu-dm-logrotate-count 10) + +# Path where persistent domain configuration is stored. +# Default is /var/lib/xend/domains/ +#(xend-domains-path /var/lib/xend/domains) diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xmexample.hvm --- a/tools/examples/xmexample.hvm Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/xmexample.hvm Thu Aug 07 11:57:34 2008 +0900 @@ -156,11 +156,6 @@ vnc=1 #---------------------------------------------------------------------------- # try to find an unused port for the VNC server, default = 1 #vncunused=1 - -#---------------------------------------------------------------------------- -# enable spawning vncviewer for domain's console -# (only valid when vnc=1), default = 0 -#vncconsole=0 #---------------------------------------------------------------------------- # set password for domain's VNC console diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xmexample.hvm-dm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/examples/xmexample.hvm-dm Thu Aug 07 11:57:34 2008 +0900 @@ -0,0 +1,14 @@ +# Not to be started directly, +# See xmexample.hvm-stubdom and stubdom/README for more details + +kernel = "/usr/lib/xen/boot/ioemu-stubdom.gz" + +# Must be the same as in xmexample.hvm-stubdom, with a prepended vif for TCP/IP +# networking in the stubdomain itself, here just '' +vif = [ '', 'type=ioemu, bridge=xenbr0' ] + +# Set here instead of in xmexample.hvm-stubdom +disk = [ 'file:/var/images/min-el3-i386.img,hda,w', ',hdc:cdrom,r' ] + +# Actual output via PVFB +vfb = [ 'type=sdl' ] diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xmexample.hvm-stubdom --- a/tools/examples/xmexample.hvm-stubdom Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/xmexample.hvm-stubdom Thu Aug 07 11:57:34 2008 +0900 @@ -7,7 +7,7 @@ #============================================================================ # # This is a version using a stubdomain for device model, see -# stubdom-ExampleHVMDomain and stubdom/README for more details +# xmexample.hvm-dm and README.stubdom for more details # The differences with xmexample.hvm are marked with "STUBDOM" #---------------------------------------------------------------------------- @@ -30,7 +30,7 @@ memory = 128 # shadow_memory = 8 # A name for your domain. All domains must have different names. -name = "ExampleHVMDomain" +name = "xmexample.hvm" # 128-bit UUID for the domain. The default behavior is to generate a new UUID # on each call to 'xm create'. diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xmexample.pv-grub --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/examples/xmexample.pv-grub Thu Aug 07 11:57:34 2008 +0900 @@ -0,0 +1,212 @@ +# -*- mode: python; -*- +#============================================================================ +# Python configuration setup for 'xm create'. +# This script sets the parameters used when a domain is created using 'xm create'. +# You use a separate script for each domain you want to create, or +# you can set the parameters for the domain on the xm command line. +#============================================================================ + +#---------------------------------------------------------------------------- +# PV GRUB image file. +kernel = "/usr/lib/xen/boot/pv-grub.gz" + +# Optional provided menu.lst. +#ramdisk = "/boot/guests/menu.lst" + +# Sets path to menu.lst +extra = "(hd0,0)/boot/grub/menu.lst" +# can be a TFTP-served path (DHCP will automatically be run) +# extra = "(nd)/netboot/menu.lst" +# can be configured automatically by GRUB's DHCP option 150 (see grub manual) +# extra = "" + +# Initial memory allocation (in megabytes) for the new domain. +# +# WARNING: Creating a domain with insufficient memory may cause out of +# memory errors. The domain needs enough memory to boot kernel +# and modules. Allocating less than 32MBs is not recommended. +memory = 64 + +# A name for your domain. All domains must have different names. +name = "ExampleDomain" + +# 128-bit UUID for the domain. The default behavior is to generate a new UUID +# on each call to 'xm create'. +#uuid = "06ed00fe-1162-4fc4-b5d8-11993ee4a8b9" + +# List of which CPUS this domain is allowed to use, default Xen picks +#cpus = "" # leave to Xen to pick +#cpus = "0" # all vcpus run on CPU0 +#cpus = "0-3,5,^1" # all vcpus run on cpus 0,2,3,5 +#cpus = ["2", "3"] # VCPU0 runs on CPU2, VCPU1 runs on CPU3 + +# Number of Virtual CPUS to use, default is 1 +#vcpus = 1 + +#---------------------------------------------------------------------------- +# Define network interfaces. + +# By default, no network interfaces are configured. You may have one created +# with sensible defaults using an empty vif clause: +# +# vif = [ '' ] +# +# or optionally override backend, bridge, ip, mac, script, type, or vifname: +# +# vif = [ 'mac=00:16:3e:00:00:11, bridge=xenbr0' ] +# +# or more than one interface may be configured: +# +# vif = [ '', 'bridge=xenbr1' ] + +vif = [ '' ] + +#---------------------------------------------------------------------------- +# Define the disk devices you want the domain to have access to, and +# what you want them accessible as. +# Each disk entry is of the form phy:UNAME,DEV,MODE +# where UNAME is the device, DEV is the device name the domain will see, +# and MODE is r for read-only, w for read-write. + +disk = [ 'phy:hda1,hda1,w' ] + +#---------------------------------------------------------------------------- +# Define frame buffer device. +# +# By default, no frame buffer device is configured. +# +# To create one using the SDL backend and sensible defaults: +# +# vfb = [ 'type=sdl' ] +# +# This uses environment variables XAUTHORITY and DISPLAY. You +# can override that: +# +# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ] +# +# To create one using the VNC backend and sensible defaults: +# +# vfb = [ 'type=vnc' ] +# +# The backend listens on 127.0.0.1 port 5900+N by default, where N is +# the domain ID. You can override both address and N: +# +# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=1' ] +# +# Or you can bind the first unused port above 5900: +# +# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vncunused=1' ] +# +# You can override the password: +# +# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ] +# +# Empty password disables authentication. Defaults to the vncpasswd +# configured in xend-config.sxp. + +#---------------------------------------------------------------------------- +# Define to which TPM instance the user domain should communicate. +# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM' +# where INSTANCE indicates the instance number of the TPM the VM +# should be talking to and DOM provides the domain where the backend +# is located. +# Note that no two virtual machines should try to connect to the same +# TPM instance. The handling of all TPM instances does require +# some management effort in so far that VM configration files (and thus +# a VM) should be associated with a TPM instance throughout the lifetime +# of the VM / VM configuration file. The instance number must be +# greater or equal to 1. +#vtpm = [ 'instance=1,backend=0' ] + +#---------------------------------------------------------------------------- +# Set the kernel command line for the new domain. +# You only need to define the IP parameters and hostname if the domain's +# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP. +# You can use 'extra' to set the runlevel and custom environment +# variables used by custom rc scripts (e.g. VMID=, usr= ). + +# Set if you want dhcp to allocate the IP address. +#dhcp="dhcp" +# Set netmask. +#netmask= +# Set default gateway. +#gateway= +# Set the hostname. +#hostname= "vm%d" % vmid + +# Set root device. +root = "/dev/hda1 ro" + +# Root device for nfs. +#root = "/dev/nfs" +# The nfs server. +#nfs_server = '192.0.2.1' +# Root directory on the nfs server. +#nfs_root = '/full/path/to/root/directory' + +#---------------------------------------------------------------------------- +# Configure the behaviour when a domain exits. There are three 'reasons' +# for a domain to stop: poweroff, reboot, and crash. For each of these you +# may specify: +# +# "destroy", meaning that the domain is cleaned up as normal; +# "restart", meaning that a new domain is started in place of the old +# one; +# "preserve", meaning that no clean-up is done until the domain is +# manually destroyed (using xm destroy, for example); or +# "rename-restart", meaning that the old domain is not cleaned up, but is +# renamed and a new domain started in its place. +# +# In the event a domain stops due to a crash, you have the additional options: +# +# "coredump-destroy", meaning dump the crashed domain's core and then destroy; +# "coredump-restart', meaning dump the crashed domain's core and the restart. +# +# The default is +# +# on_poweroff = 'destroy' +# on_reboot = 'restart' +# on_crash = 'restart' +# +# For backwards compatibility we also support the deprecated option restart +# +# restart = 'onreboot' means on_poweroff = 'destroy' +# on_reboot = 'restart' +# on_crash = 'destroy' +# +# restart = 'always' means on_poweroff = 'restart' +# on_reboot = 'restart' +# on_crash = 'restart' +# +# restart = 'never' means on_poweroff = 'destroy' +# on_reboot = 'destroy' +# on_crash = 'destroy' + +#on_poweroff = 'destroy' +#on_reboot = 'restart' +#on_crash = 'restart' + +#----------------------------------------------------------------------------- +# Configure PVSCSI devices: +# +#vscsi=[ 'PDEV, VDEV' ] +# +# PDEV gives physical SCSI device to be attached to specified guest +# domain by one of the following identifier format. +# - XX:XX:XX:XX (4-tuples with decimal notation which shows +# "host:channel:target:lun") +# - /dev/sdxx or sdx +# - /dev/stxx or stx +# - /dev/sgxx or sgx +# - result of 'scsi_id -gu -s'. +# ex. # scsi_id -gu -s /block/sdb +# 36000b5d0006a0000006a0257004c0000 +# +# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as +# which the specified guest domain recognize. +# + +#vscsi = [ '/dev/sdx, 0:0:0:0' ] + +#============================================================================ + diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xmexample.vti --- a/tools/examples/xmexample.vti Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/xmexample.vti Thu Aug 07 11:57:34 2008 +0900 @@ -95,11 +95,6 @@ vnc=0 #vncunused=1 #---------------------------------------------------------------------------- -# enable spawning vncviewer for domain's console -# (only valid when vnc=1), default = 0 -#vncconsole=0 - -#---------------------------------------------------------------------------- # set password for domain's VNC console # default is depents on vncpasswd in xend-config.sxp vncpasswd='' diff -r 7affdebb7a1e -r a39913db6e51 tools/examples/xmexample3 --- a/tools/examples/xmexample3 Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/examples/xmexample3 Thu Aug 07 11:57:34 2008 +0900 @@ -207,4 +207,26 @@ extra = "4 VMID=%d" % vmid #on_reboot = 'restart' #on_crash = 'restart' -#============================================================================ +#----------------------------------------------------------------------------- +# Configure PVSCSI devices: +# +#vscsi=[ 'PDEV, VDEV' ] +# +# PDEV gives physical SCSI device to be attached to specified guest +# domain by one of the following identifier format. +# - XX:XX:XX:XX (4-tuples with decimal notation which shows +# "host:channel:target:lun") +# - /dev/sdxx or sdx +# - /dev/stxx or stx +# - /dev/sgxx or sgx +# - result of 'scsi_id -gu -s'. +# ex. # scsi_id -gu -s /block/sdb +# 36000b5d0006a0000006a0257004c0000 +# +# VDEV gives virtual SCSI device by 4-tuples (XX:XX:XX:XX) as +# which the specified guest domain recognize. +# + +#vscsi = [ '/dev/sdx, 0:0:0:0' ] + +#============================================================================ diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/extboot/Makefile --- a/tools/firmware/extboot/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/extboot/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -1,7 +1,5 @@ XEN_ROOT = ../../.. XEN_ROOT = ../../.. include $(XEN_ROOT)/tools/firmware/Rules.mk - -CFLAGS += -I$(XEN_ROOT)/tools/libxc -I. .PHONY: all all: extboot.bin diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/hvmloader/Makefile --- a/tools/firmware/hvmloader/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/hvmloader/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -33,14 +33,14 @@ OBJS = $(patsubst %.c,%.o,$(SRCS)) OBJS = $(patsubst %.c,%.o,$(SRCS)) .PHONY: all -all: hvmloader +all: subdirs-all + $(MAKE) hvmloader hvmloader.o: roms.h smbios.o: CFLAGS += -D__SMBIOS_DATE__="\"$(shell date +%m/%d/%Y)\"" -hvmloader: subdirs-all $(OBJS) - $(LD) $(LDFLAGS_DIRECT) -N -Ttext $(LOADADDR) \ - -o hvmloader.tmp $(OBJS) acpi/acpi.a +hvmloader: $(OBJS) acpi/acpi.a + $(LD) $(LDFLAGS_DIRECT) -N -Ttext $(LOADADDR) -o hvmloader.tmp $^ $(OBJCOPY) hvmloader.tmp hvmloader rm -f hvmloader.tmp diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/hvmloader/acpi/acpi2_0.h --- a/tools/firmware/hvmloader/acpi/acpi2_0.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/hvmloader/acpi/acpi2_0.h Thu Aug 07 11:57:34 2008 +0900 @@ -381,7 +381,7 @@ struct acpi_20_madt_intsrcovr { #pragma pack () -int acpi_build_tables(uint8_t *); +void acpi_build_tables(void); #endif /* _ACPI_2_0_H_ */ diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/hvmloader/acpi/build.c --- a/tools/firmware/hvmloader/acpi/build.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/hvmloader/acpi/build.c Thu Aug 07 11:57:34 2008 +0900 @@ -248,8 +248,7 @@ static int construct_secondary_tables(ui return align16(offset); } -/* Copy all the ACPI table to buffer. */ -int acpi_build_tables(uint8_t *buf) +static void __acpi_build_tables(uint8_t *buf, int *low_sz, int *high_sz) { struct acpi_20_rsdp *rsdp; struct acpi_20_rsdt *rsdt; @@ -261,7 +260,9 @@ int acpi_build_tables(uint8_t *buf) unsigned long secondary_tables[16]; int offset = 0, i; - offset += construct_bios_info_table(&buf[offset]); + /* + * Fill in high-memory data structures, starting at @buf. + */ facs = (struct acpi_20_facs *)&buf[offset]; memcpy(facs, &Facs, sizeof(struct acpi_20_facs)); @@ -325,7 +326,18 @@ int acpi_build_tables(uint8_t *buf) offsetof(struct acpi_header, checksum), rsdt->header.length); + *high_sz = offset; + + /* + * Fill in low-memory data structures: bios_info_table and RSDP. + */ + + buf = (uint8_t *)ACPI_PHYSICAL_ADDRESS; + offset = 0; + + offset += construct_bios_info_table(&buf[offset]); rsdp = (struct acpi_20_rsdp *)&buf[offset]; + memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp)); offset += align16(sizeof(struct acpi_20_rsdp)); rsdp->rsdt_address = (unsigned long)rsdt; @@ -337,7 +349,28 @@ int acpi_build_tables(uint8_t *buf) offsetof(struct acpi_20_rsdp, extended_checksum), sizeof(struct acpi_20_rsdp)); - return offset; + *low_sz = offset; +} + +void acpi_build_tables(void) +{ + int high_sz, low_sz; + uint8_t *buf; + + /* Find out size of high-memory ACPI data area. */ + buf = (uint8_t *)&_end; + __acpi_build_tables(buf, &low_sz, &high_sz); + memset(buf, 0, high_sz); + + /* Allocate data area and set up ACPI tables there. */ + buf = (uint8_t *)e820_malloc(high_sz); + __acpi_build_tables(buf, &low_sz, &high_sz); + + printf(" - Lo data: %08lx-%08lx\n" + " - Hi data: %08lx-%08lx\n", + (unsigned long)ACPI_PHYSICAL_ADDRESS, + (unsigned long)ACPI_PHYSICAL_ADDRESS + low_sz - 1, + (unsigned long)buf, (unsigned long)buf + high_sz - 1); } /* diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/hvmloader/hvmloader.c --- a/tools/firmware/hvmloader/hvmloader.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/hvmloader/hvmloader.c Thu Aug 07 11:57:34 2008 +0900 @@ -449,7 +449,7 @@ static void init_xen_platform_io_base(vo int main(void) { - int acpi_sz = 0, vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz; + int vgabios_sz = 0, etherboot_sz = 0, rombios_sz, smbios_sz; int extboot_sz = 0; printf("HVM Loader\n"); @@ -508,8 +508,7 @@ int main(void) if ( get_acpi_enabled() ) { printf("Loading ACPI ...\n"); - acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS); - ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000); + acpi_build_tables(); } cmos_write_memory_size(); @@ -531,10 +530,6 @@ int main(void) printf(" %05x-%05x: SMBIOS tables\n", SMBIOS_PHYSICAL_ADDRESS, SMBIOS_PHYSICAL_ADDRESS + smbios_sz - 1); - if ( acpi_sz ) - printf(" %05x-%05x: ACPI tables\n", - ACPI_PHYSICAL_ADDRESS, - ACPI_PHYSICAL_ADDRESS + acpi_sz - 1); if ( rombios_sz ) printf(" %05x-%05x: Main BIOS\n", ROMBIOS_PHYSICAL_ADDRESS, diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/hvmloader/util.h --- a/tools/firmware/hvmloader/util.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/hvmloader/util.h Thu Aug 07 11:57:34 2008 +0900 @@ -145,4 +145,6 @@ void smp_initialise(void); #define isdigit(c) ((c) >= '0' && (c) <= '9') +extern char _start[], _end[]; + #endif /* __HVMLOADER_UTIL_H__ */ diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/32bitbios.c --- a/tools/firmware/rombios/32bit/32bitbios.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/32bitbios.c Thu Aug 07 11:57:34 2008 +0900 @@ -47,5 +47,7 @@ uint32_t jumptable[IDX_LAST+1] __attribu TABLE_ENTRY(IDX_TCPA_INITIALIZE_TPM, tcpa_initialize_tpm), + TABLE_ENTRY(IDX_GET_S3_WAKING_VECTOR, get_s3_waking_vector), + TABLE_ENTRY(IDX_LAST , 0) /* keep last */ }; diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/Makefile --- a/tools/firmware/rombios/32bit/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -4,21 +4,22 @@ SOURCES = util.c SOURCES = util.c TARGET = 32bitbios_flat.h -CFLAGS += -I../ -DGCC_PROTOS +CFLAGS += $(CFLAGS_include) -I.. -DGCC_PROTOS SUBDIRS = tcgbios MODULES = tcgbios/tcgbiosext.o .PHONY: all -all: $(TARGET) +all: subdirs-all + $(MAKE) $(TARGET) .PHONY: clean clean: subdirs-clean rm -rf *.o $(TARGET) -$(TARGET): subdirs-all 32bitbios.o util.o - $(LD) $(LDFLAGS_DIRECT) -s -r 32bitbios.o $(MODULES) util.o -o 32bitbios_all.o +$(TARGET): 32bitbios.o $(MODULES) util.o + $(LD) $(LDFLAGS_DIRECT) -s -r $^ -o 32bitbios_all.o @nm 32bitbios_all.o | \ egrep '^ +U ' >/dev/null && { \ echo "There are undefined symbols in the BIOS:"; \ diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/tcgbios/Makefile --- a/tools/firmware/rombios/32bit/tcgbios/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/tcgbios/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -5,7 +5,7 @@ FILES = tcgbios tpm_drivers FILES = tcgbios tpm_drivers OBJECTS = $(foreach f,$(FILES),$(f).o) -CFLAGS += -I../ -I../../ -DGCC_PROTOS +CFLAGS += $(CFLAGS_include) -I.. -I../.. -DGCC_PROTOS .PHONY: all clean diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/tcgbios/tcgbios.c --- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c Thu Aug 07 11:57:34 2008 +0900 @@ -24,10 +24,9 @@ #include "rombios_compat.h" #include "tpm_drivers.h" +#include "util.h" #include "tcgbios.h" #include "32bitprotos.h" -#include "util.h" - /* local structure and variables */ struct ptti_cust { @@ -135,7 +134,7 @@ static inline uint32_t bswap(uint32_t a) *******************************************************/ typedef struct { - struct acpi_20_tcpa *tcpa_ptr; + struct acpi_20_tcpa_clisrv *tcpa_ptr; unsigned char *lasa_last_ptr; uint16_t entry_count; uint16_t flags; @@ -260,45 +259,19 @@ uint8_t acpi_validate_entry(struct acpi_ } -/* - * Search for the RSDP ACPI table in the memory starting at addr and - * ending at addr + len - 1. - */ -static struct acpi_20_rsdp *find_rsdp(const void *start, unsigned int len) -{ - char *rsdp = (char *)start; - char *end = rsdp + len; - /* scan memory in steps of 16 bytes */ - while (rsdp < end) { - /* check for expected string */ - if (!strncmp( rsdp, "RSD PTR ", 8)) - return (struct acpi_20_rsdp *)rsdp; - rsdp += 0x10; - } - return 0; -} - void tcpa_acpi_init(void) { struct acpi_20_rsdt *rsdt; - struct acpi_20_tcpa *tcpa = (void *)0; + struct acpi_20_tcpa_clisrv *tcpa = (void *)0; struct acpi_20_rsdp *rsdp; uint32_t length; uint16_t off; int found = 0; - uint16_t ebda_seg; - - if (MA_IsTPMPresent() == 0) { + + if (MA_IsTPMPresent() == 0) return; - } - - /* RSDP in EBDA? */ - ebda_seg = *(uint16_t *)ADDR_FROM_SEG_OFF(0x40, 0xe); - rsdp = find_rsdp((void *)(ebda_seg << 16), 1024); - - if (!rsdp) - rsdp = find_rsdp((void *)(ACPI_SEGMENT << 4), 0x20000); - + + rsdp = find_rsdp(); if (rsdp) { uint32_t ctr = 0; /* get RSDT from RSDP */ @@ -307,7 +280,7 @@ void tcpa_acpi_init(void) off = 36; while ((off + 3) < length) { /* try all pointers to structures */ - tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr]; + tcpa = (struct acpi_20_tcpa_clisrv *)rsdt->entry[ctr]; /* valid TCPA ACPI table ? */ if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature && acpi_validate_entry(&tcpa->header) == 0) { @@ -398,7 +371,7 @@ unsigned char *tcpa_get_lasa_base_ptr(vo unsigned char *tcpa_get_lasa_base_ptr(void) { unsigned char *lasa = 0; - struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr; + struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr; if (tcpa != 0) { uint32_t class = tcpa->platform_class; if (class == TCPA_ACPI_CLASS_CLIENT) { @@ -416,7 +389,7 @@ uint32_t tcpa_get_laml(void) uint32_t tcpa_get_laml(void) { uint32_t laml = 0; - struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr; + struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr; if (tcpa != 0) { uint32_t class = tcpa->platform_class; if (class == TCPA_ACPI_CLASS_CLIENT) { diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/tcgbios/tcgbios.h --- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.h Thu Aug 07 11:57:34 2008 +0900 @@ -1,6 +1,5 @@ #ifndef TCGBIOS_H #define TCGBIOS_H - /* TCPA ACPI definitions */ #define TCPA_ACPI_CLASS_CLIENT 0 @@ -117,14 +116,7 @@ /* address of locality 0 (TIS) */ #define TPM_TIS_BASE_ADDRESS 0xfed40000 -#define ASCII32(a,b,c,d) ((((Bit32u)a) << 0) | (((Bit32u)b) << 8) | \ - (((Bit32u)c) << 16) | (((Bit32u)d) << 24) ) -#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A') /* "TCPA" */ - - #define STATUS_FLAG_SHUTDOWN (1 << 0) - -#define ACPI_SEGMENT 0xE000 /* Input and Output blocks for the TCG BIOS commands */ @@ -232,37 +224,6 @@ struct pcpes uint32_t event; } __attribute__((packed)); - -struct acpi_header -{ - uint32_t signature; - uint32_t length; - uint8_t revision; - uint8_t checksum; - uint8_t oem_id[6]; - uint64_t oem_table_id; - uint32_t oem_revision; - uint32_t creator_id; - uint32_t creator_revision; -} __attribute__((packed)); - -struct acpi_20_rsdt { - struct acpi_header header; - uint32_t entry[1]; -} __attribute__((packed)); - -struct acpi_20_rsdp { - uint64_t signature; - uint8_t checksum; - uint8_t oem_id[6]; - uint8_t revision; - uint32_t rsdt_address; - uint32_t length; - uint64_t xsdt_address; - uint8_t extended_checksum; - uint8_t reserved[3]; -} __attribute__((packed)); - struct acpi_20_tcpa_client { uint32_t laml; uint64_t lasa; @@ -275,7 +236,7 @@ struct acpi_20_tcpa_server { /* more here */ } __attribute__((packed)); -struct acpi_20_tcpa { +struct acpi_20_tcpa_clisrv { struct acpi_header header; uint16_t platform_class; union { diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/util.c --- a/tools/firmware/rombios/32bit/util.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/util.c Thu Aug 07 11:57:34 2008 +0900 @@ -19,6 +19,7 @@ */ #include <stdarg.h> #include <stdint.h> +#include "rombios_compat.h" #include "util.h" static void putchar(char c); @@ -92,11 +93,11 @@ int strcmp(const char *cs, const char *c int strncmp(const char *s1, const char *s2, uint32_t n) { - uint32_t ctr; - for (ctr = 0; ctr < n; ctr++) - if (s1[ctr] != s2[ctr]) - return (int)(s1[ctr] - s2[ctr]); - return 0; + uint32_t ctr; + for (ctr = 0; ctr < n; ctr++) + if (s1[ctr] != s2[ctr]) + return (int)(s1[ctr] - s2[ctr]); + return 0; } void *memcpy(void *dest, const void *src, unsigned n) @@ -402,3 +403,64 @@ void mssleep(uint32_t waittime) y = x; } } + +/* + * Search for the RSDP ACPI table in the memory starting at addr and + * ending at addr + len - 1. + */ +static struct acpi_20_rsdp *__find_rsdp(const void *start, unsigned int len) +{ + char *rsdp = (char *)start; + char *end = rsdp + len; + /* scan memory in steps of 16 bytes */ + while (rsdp < end) { + /* check for expected string */ + if (!strncmp(rsdp, "RSD PTR ", 8)) + return (struct acpi_20_rsdp *)rsdp; + rsdp += 0x10; + } + return 0; +} + +struct acpi_20_rsdp *find_rsdp(void) +{ + struct acpi_20_rsdp *rsdp; + uint16_t ebda_seg; + + ebda_seg = *(uint16_t *)ADDR_FROM_SEG_OFF(0x40, 0xe); + rsdp = __find_rsdp((void *)(ebda_seg << 16), 1024); + if (!rsdp) + rsdp = __find_rsdp((void *)0xE0000, 0x20000); + + return rsdp; +} + +uint32_t get_s3_waking_vector(void) +{ + struct acpi_20_rsdp *rsdp = find_rsdp(); + struct acpi_20_xsdt *xsdt; + struct acpi_20_fadt *fadt; + struct acpi_20_facs *facs; + uint32_t vector; + + if (!rsdp) + return 0; + + xsdt = (struct acpi_20_xsdt *)(long)rsdp->xsdt_address; + if (!xsdt) + return 0; + + fadt = (struct acpi_20_fadt *)(long)xsdt->entry[0]; + if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE)) + return 0; + + facs = (struct acpi_20_facs *)(long)fadt->x_firmware_ctrl; + if (!facs) + return 0; + + vector = facs->x_firmware_waking_vector; + if (!vector) + vector = facs->firmware_waking_vector; + + return vector; +} diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bit/util.h --- a/tools/firmware/rombios/32bit/util.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bit/util.h Thu Aug 07 11:57:34 2008 +0900 @@ -1,5 +1,7 @@ #ifndef UTIL_H #define UTIL_H + +#include "../hvmloader/acpi/acpi2_0.h" void outb(uint16_t addr, uint8_t val); void outw(uint16_t addr, uint16_t val); @@ -39,5 +41,6 @@ static inline uint32_t mmio_readl(uint32 return *(volatile uint32_t *)addr; } +struct acpi_20_rsdp *find_rsdp(void); #endif diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bitgateway.c --- a/tools/firmware/rombios/32bitgateway.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bitgateway.c Thu Aug 07 11:57:34 2008 +0900 @@ -356,6 +356,9 @@ Upcall: call _store_returnaddress ; store away pop ax + ; XXX GDT munging requires ROM to be writable! + call _enable_rom_write_access + rol bx, #2 mov si, #jmptable seg cs @@ -381,6 +384,8 @@ Upcall: push bp mov bp,sp push eax ; preserve work register + + call _disable_rom_write_access call _get_returnaddress mov 2[bp], ax ; 16bit return address onto stack @@ -408,3 +413,10 @@ ASM_END #include "32bitgateway.h" #include "tcgbios.c" + +Bit32u get_s3_waking_vector() +{ + ASM_START + DoUpcall(IDX_GET_S3_WAKING_VECTOR) + ASM_END +} diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/32bitprotos.h --- a/tools/firmware/rombios/32bitprotos.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/32bitprotos.h Thu Aug 07 11:57:34 2008 +0900 @@ -17,8 +17,8 @@ #define IDX_TCPA_IPL 10 #define IDX_TCPA_INITIALIZE_TPM 11 #define IDX_TCPA_MEASURE_POST 12 - -#define IDX_LAST 13 /* keep last! */ +#define IDX_GET_S3_WAKING_VECTOR 13 +#define IDX_LAST 14 /* keep last! */ #ifdef GCC_PROTOS #define PARMS(x...) x @@ -42,4 +42,6 @@ void tcpa_measure_post( PARMS(Bit32u fro void tcpa_measure_post( PARMS(Bit32u from, Bit32u to) ); Bit32u tcpa_initialize_tpm( PARMS(Bit32u physpres) ); +Bit32u get_s3_waking_vector( PARMS(void) ); + #endif diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/Makefile --- a/tools/firmware/rombios/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -4,7 +4,8 @@ SUBDIRS := 32bit SUBDIRS := 32bit .PHONY: all -all: subdirs-all BIOS-bochs-latest +all: subdirs-all + $(MAKE) BIOS-bochs-latest .PHONY: clean clean: subdirs-clean diff -r 7affdebb7a1e -r a39913db6e51 tools/firmware/rombios/rombios.c --- a/tools/firmware/rombios/rombios.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/firmware/rombios/rombios.c Thu Aug 07 11:57:34 2008 +0900 @@ -738,7 +738,9 @@ typedef struct { // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot // device tables are at 0x9ff00 -- 0x9ffff typedef struct { - unsigned char filler1[0x3D]; + unsigned char ebda_size; + unsigned char cmos_shutdown_status; + unsigned char filler1[0x3B]; // FDPT - Can be splitted in data members if needed unsigned char fdpt0[0x10]; @@ -757,6 +759,7 @@ typedef struct { upcall_t upcall; } ebda_data_t; + #define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1 #define EbdaData ((ebda_data_t *) 0) // for access to the int13ext structure @@ -1464,19 +1467,30 @@ copy_e820_table() } void -disable_rom_write_access() +set_rom_write_access(action) + Bit16u action; { Bit16u off = (Bit16u)&((struct bios_info *)0)->xen_pfiob; ASM_START - mov si,.disable_rom_write_access.off[bp] + mov si,.set_rom_write_access.off[bp] push ds mov ax,#(ACPI_PHYSICAL_ADDRESS >> 4) mov ds,ax mov dx,[si] pop ds - mov ax,#PFFLAG_ROM_LOCK + mov ax,.set_rom_write_access.action[bp] out dx,al ASM_END +} + +void enable_rom_write_access() +{ + set_rom_write_access(0); +} + +void disable_rom_write_access() +{ + set_rom_write_access(PFFLAG_ROM_LOCK); } #endif /* HVMASSIST */ @@ -2325,78 +2339,38 @@ debugger_off() outb(0xfedc, 0x00); } -/* according to memory layout defined in acpi_build_tables(), - acpi FACS table is located in ACPI_PHYSICAL_ADDRESS(0xEA000) */ -#define ACPI_FACS_ADDRESS 0xEA000 -#define ACPI_FACS_OFFSET 0x10 -/* S3 resume status in CMOS 0Fh shutdown status byte*/ - -Bit32u facs_get32(offs) -Bit16u offs; -{ -ASM_START - push bp - mov bp, sp - - push ds - mov ax, #(ACPI_FACS_ADDRESS >> 4) - mov ds, ax - - mov bx, 4[bp] - mov ax, [bx] - mov dx, 2[bx] - pop ds - - pop bp -ASM_END -} - - void s3_resume() { Bit32u s3_wakeup_vector; - extern Bit16u s3_wakeup_ip; - extern Bit16u s3_wakeup_cs; - extern Bit8u s3_resume_flag; + Bit16u s3_wakeup_ip, s3_wakeup_cs; + Bit8u cmos_shutdown_status; ASM_START push ds - mov ax, #0xF000 + push ax + mov ax, #EBDA_SEG mov ds, ax + mov al, [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET] + mov .s3_resume.cmos_shutdown_status[bp], al + pop ax + pop ds ASM_END - if (s3_resume_flag!=CMOS_SHUTDOWN_S3){ - goto s3_out; - } - s3_resume_flag = 0; - - /* get x_firmware_waking_vector */ - s3_wakeup_vector = facs_get32(ACPI_FACS_OFFSET+24); - if (!s3_wakeup_vector) { - /* get firmware_waking_vector */ - s3_wakeup_vector = facs_get32(ACPI_FACS_OFFSET+12); - if (!s3_wakeup_vector) { - goto s3_out; - } - } - - /* setup wakeup vector */ + if (cmos_shutdown_status != CMOS_SHUTDOWN_S3) + return; + + s3_wakeup_vector = get_s3_waking_vector(); + if (!s3_wakeup_vector) + return; + s3_wakeup_ip = s3_wakeup_vector & 0xF; s3_wakeup_cs = s3_wakeup_vector >> 4; ASM_START - jmpf [_s3_wakeup_ip] - -; S3 data -_s3_wakeup_ip: dw 0x0a -_s3_wakeup_cs: dw 0x0 -_s3_resume_flag: db 0 ; set at POST time by CMOS[0xF] shutdown status -ASM_END - -s3_out: -ASM_START - pop ds + push .s3_resume.s3_wakeup_cs[bp] + push .s3_resume.s3_wakeup_ip[bp] + retf ASM_END } @@ -9865,52 +9839,9 @@ post: ;; Examine CMOS shutdown status. mov al, bl - - ;; 0xFE S3 resume - cmp AL, #0xFE - jnz not_s3_resume - - ;; set S3 resume flag - mov dx, #0xF000 + mov dx, #EBDA_SEG mov ds, dx - mov [_s3_resume_flag], AL - jmp normal_post - -not_s3_resume: - - ;; 0x00, 0x09, 0x0D+ = normal startup - cmp AL, #0x00 - jz normal_post - cmp AL, #0x0d - jae normal_post - cmp AL, #0x09 - je normal_post - - ;; 0x05 = eoi + jmp via [0x40:0x67] jump - cmp al, #0x05 - je eoi_jmp_post - - ;; Examine CMOS shutdown status. - ;; 0x01,0x02,0x03,0x04,0x06,0x07,0x08, 0x0a, 0x0b, 0x0c = Unimplemented shutdown status. - push bx - call _shutdown_status_panic - -#if 0 - HALT(__LINE__) - ; - ;#if 0 - ; 0xb0, 0x20, /* mov al, #0x20 */ - ; 0xe6, 0x20, /* out 0x20, al ;send EOI to PIC */ - ;#endif - ; - pop es - pop ds - popa - iret -#endif - -normal_post: - ; case 0: normal startup + mov [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET], AL cli mov ax, #0xfffe @@ -9928,8 +9859,6 @@ normal_post: stosw call _log_bios_start - - call _clobber_entry_point ;; set all interrupts to default handler mov bx, #0x0000 ;; offset index @@ -10123,8 +10052,11 @@ post_default_ints: out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14 #ifdef HVMASSIST + call _enable_rom_write_access + call _clobber_entry_point call _copy_e820_table call smbios_init + call _disable_rom_write_access #endif call _init_boot_vectors @@ -10174,10 +10106,6 @@ post_default_ints: #if BX_TCGBIOS call tcpa_post_part2 #endif - -#ifdef HVMASSIST - call _disable_rom_write_access -#endif ;; Start the boot sequence. See the comments in int19_relocated ;; for why we use INT 18h instead of INT 19h here. diff -r 7affdebb7a1e -r a39913db6e51 tools/fs-back/fs-backend.c --- a/tools/fs-back/fs-backend.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/fs-back/fs-backend.c Thu Aug 07 11:57:34 2008 +0900 @@ -16,7 +16,7 @@ static int export_id = 0; static int export_id = 0; static int mount_id = 0; -void dispatch_response(struct mount *mount, int priv_req_id) +static void dispatch_response(struct fs_mount *mount, int priv_req_id) { int i; struct fs_op *op; @@ -41,7 +41,7 @@ void dispatch_response(struct mount *mou add_id_to_freelist(priv_req_id, mount->freelist); } -static void handle_aio_events(struct mount *mount) +static void handle_aio_events(struct fs_mount *mount) { int fd, ret, count, i, notify; evtchn_port_t port; @@ -103,7 +103,7 @@ read_event_channel: } -void allocate_request_array(struct mount *mount) +static void allocate_request_array(struct fs_mount *mount) { int i, nr_entries = mount->nr_entries; struct fs_request *requests; @@ -123,10 +123,10 @@ void allocate_request_array(struct mount } -void* handle_mount(void *data) +static void *handle_mount(void *data) { int more, notify; - struct mount *mount = (struct mount *)data; + struct fs_mount *mount = (struct fs_mount *)data; printf("Starting a thread for mount: %d\n", mount->mount_id); allocate_request_array(mount); @@ -147,7 +147,8 @@ moretodo: int i; struct fs_op *op; - printf("Got a request at %d\n", cons); + printf("Got a request at %d (of %d)\n", + cons, RING_SIZE(&mount->ring)); req = RING_GET_REQUEST(&mount->ring, cons); printf("Request type=%d\n", req->type); for(i=0;;i++) @@ -193,11 +194,12 @@ moretodo: static void handle_connection(int frontend_dom_id, int export_id, char *frontend) { - struct mount *mount; + struct fs_mount *mount; struct fs_export *export; int evt_port; pthread_t handling_thread; struct fsif_sring *sring; + uint32_t dom_ids[MAX_RING_SIZE]; int i; printf("Handling connection from dom=%d, for export=%d\n", @@ -216,13 +218,13 @@ static void handle_connection(int fronte return; } - mount = (struct mount*)malloc(sizeof(struct mount)); + mount = (struct fs_mount*)malloc(sizeof(struct fs_mount)); mount->dom_id = frontend_dom_id; mount->export = export; mount->mount_id = mount_id++; xenbus_read_mount_request(mount, frontend); printf("Frontend found at: %s (gref=%d, evtchn=%d)\n", - mount->frontend, mount->gref, mount->remote_evtchn); + mount->frontend, mount->grefs[0], mount->remote_evtchn); xenbus_write_backend_node(mount); mount->evth = -1; mount->evth = xc_evtchn_open(); @@ -235,11 +237,15 @@ static void handle_connection(int fronte mount->gnth = -1; mount->gnth = xc_gnttab_open(); assert(mount->gnth != -1); - sring = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - mount->gref, - PROT_READ | PROT_WRITE); - BACK_RING_INIT(&mount->ring, sring, XC_PAGE_SIZE); + for(i=0; i<mount->shared_ring_size; i++) + dom_ids[i] = mount->dom_id; + sring = xc_gnttab_map_grant_refs(mount->gnth, + mount->shared_ring_size, + dom_ids, + mount->grefs, + PROT_READ | PROT_WRITE); + + BACK_RING_INIT(&mount->ring, sring, mount->shared_ring_size * XC_PAGE_SIZE); mount->nr_entries = mount->ring.nr_ents; for (i = 0; i < MAX_FDS; i++) mount->fds[i] = -1; @@ -287,7 +293,7 @@ next_select: } while (1); } -struct fs_export* create_export(char *name, char *export_path) +static struct fs_export* create_export(char *name, char *export_path) { struct fs_export *curr_export, **last_export; diff -r 7affdebb7a1e -r a39913db6e51 tools/fs-back/fs-backend.h --- a/tools/fs-back/fs-backend.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/fs-back/fs-backend.h Thu Aug 07 11:57:34 2008 +0900 @@ -13,6 +13,7 @@ #define EXPORTS_NODE ROOT_NODE"/"EXPORTS_SUBNODE #define WATCH_NODE EXPORTS_NODE"/requests" #define MAX_FDS 16 +#define MAX_RING_SIZE 16 struct fs_export { @@ -26,22 +27,24 @@ struct fs_request { int active; void *page; /* Pointer to mapped grant */ + int count; struct fsif_request req_shadow; struct aiocb aiocb; }; -struct mount +struct fs_mount { struct fs_export *export; int dom_id; char *frontend; int mount_id; /* = backend id */ - grant_ref_t gref; + grant_ref_t grefs[MAX_RING_SIZE]; evtchn_port_t remote_evtchn; int evth; /* Handle to the event channel */ evtchn_port_t local_evtchn; int gnth; + int shared_ring_size; /* in pages */ struct fsif_back_ring ring; int nr_entries; struct fs_request *requests; @@ -56,17 +59,17 @@ bool xenbus_create_request_node(void); bool xenbus_create_request_node(void); int xenbus_register_export(struct fs_export *export); int xenbus_get_watch_fd(void); -void xenbus_read_mount_request(struct mount *mount, char *frontend); -void xenbus_write_backend_node(struct mount *mount); -void xenbus_write_backend_ready(struct mount *mount); +void xenbus_read_mount_request(struct fs_mount *mount, char *frontend); +void xenbus_write_backend_node(struct fs_mount *mount); +void xenbus_write_backend_ready(struct fs_mount *mount); /* File operations, implemented in fs-ops.c */ struct fs_op { int type; /* Type of request (from fsif.h) this handlers are responsible for */ - void (*dispatch_handler)(struct mount *mount, struct fsif_request *req); - void (*response_handler)(struct mount *mount, struct fs_request *req); + void (*dispatch_handler)(struct fs_mount *mount, struct fsif_request *req); + void (*response_handler)(struct fs_mount *mount, struct fs_request *req); }; /* This NULL terminated array of all file requests handlers */ diff -r 7affdebb7a1e -r a39913db6e51 tools/fs-back/fs-ops.c --- a/tools/fs-back/fs-ops.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/fs-back/fs-ops.c Thu Aug 07 11:57:34 2008 +0900 @@ -10,7 +10,7 @@ #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> -#include <sys/vfs.h> +#include <sys/statvfs.h> #include <sys/mount.h> #include <unistd.h> #include "fs-backend.h" @@ -23,7 +23,7 @@ #define BUFFER_SIZE 1024 -unsigned short get_request(struct mount *mount, struct fsif_request *req) +static unsigned short get_request(struct fs_mount *mount, struct fsif_request *req) { unsigned short id = get_id_from_freelist(mount->freelist); @@ -34,7 +34,7 @@ unsigned short get_request(struct mount return id; } -int get_fd(struct mount *mount) +static int get_fd(struct fs_mount *mount) { int i; @@ -45,7 +45,7 @@ int get_fd(struct mount *mount) } -void dispatch_file_open(struct mount *mount, struct fsif_request *req) +static void dispatch_file_open(struct fs_mount *mount, struct fsif_request *req) { char *file_name, full_path[BUFFER_SIZE]; int fd; @@ -93,7 +93,7 @@ void dispatch_file_open(struct mount *mo rsp->ret_val = (uint64_t)fd; } -void dispatch_file_close(struct mount *mount, struct fsif_request *req) +static void dispatch_file_close(struct fs_mount *mount, struct fsif_request *req) { int ret; RING_IDX rsp_idx; @@ -122,19 +122,25 @@ void dispatch_file_close(struct mount *m rsp->id = req_id; rsp->ret_val = (uint64_t)ret; } -void dispatch_file_read(struct mount *mount, struct fsif_request *req) + +#define MAX_GNTS 16 +static void dispatch_file_read(struct fs_mount *mount, struct fsif_request *req) { void *buf; - int fd; + int fd, i, count; uint16_t req_id; unsigned short priv_id; struct fs_request *priv_req; /* Read the request */ - buf = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fread.gref, - PROT_WRITE); + assert(req->u.fread.len > 0); + count = (req->u.fread.len - 1) / XC_PAGE_SIZE + 1; + assert(count <= FSIF_NR_READ_GNTS); + buf = xc_gnttab_map_domain_grant_refs(mount->gnth, + count, + mount->dom_id, + req->u.fread.grefs, + PROT_WRITE); req_id = req->id; printf("File read issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", @@ -149,6 +155,7 @@ void dispatch_file_read(struct mount *mo printf("Private id is: %d\n", priv_id); priv_req = &mount->requests[priv_id]; priv_req->page = buf; + priv_req->count = count; /* Dispatch AIO read request */ bzero(&priv_req->aiocb, sizeof(struct aiocb)); @@ -164,14 +171,16 @@ out: mount->ring.req_cons++; } -void end_file_read(struct mount *mount, struct fs_request *priv_req) +static void end_file_read(struct fs_mount *mount, struct fs_request *priv_req) { RING_IDX rsp_idx; fsif_response_t *rsp; uint16_t req_id; /* Release the grant */ - assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0); + assert(xc_gnttab_munmap(mount->gnth, + priv_req->page, + priv_req->count) == 0); /* Get a response from the ring */ rsp_idx = mount->ring.rsp_prod_pvt++; @@ -182,19 +191,23 @@ void end_file_read(struct mount *mount, rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb); } -void dispatch_file_write(struct mount *mount, struct fsif_request *req) +static void dispatch_file_write(struct fs_mount *mount, struct fsif_request *req) { void *buf; - int fd; + int fd, count, i; uint16_t req_id; unsigned short priv_id; struct fs_request *priv_req; /* Read the request */ - buf = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fwrite.gref, - PROT_READ); + assert(req->u.fwrite.len > 0); + count = (req->u.fwrite.len - 1) / XC_PAGE_SIZE + 1; + assert(count <= FSIF_NR_WRITE_GNTS); + buf = xc_gnttab_map_domain_grant_refs(mount->gnth, + count, + mount->dom_id, + req->u.fwrite.grefs, + PROT_READ); req_id = req->id; printf("File write issued for FD=%d (len=%"PRIu64", offest=%"PRIu64")\n", @@ -209,6 +222,7 @@ void dispatch_file_write(struct mount *m printf("Private id is: %d\n", priv_id); priv_req = &mount->requests[priv_id]; priv_req->page = buf; + priv_req->count = count; /* Dispatch AIO write request */ bzero(&priv_req->aiocb, sizeof(struct aiocb)); @@ -224,14 +238,16 @@ void dispatch_file_write(struct mount *m mount->ring.req_cons++; } -void end_file_write(struct mount *mount, struct fs_request *priv_req) +static void end_file_write(struct fs_mount *mount, struct fs_request *priv_req) { RING_IDX rsp_idx; fsif_response_t *rsp; uint16_t req_id; /* Release the grant */ - assert(xc_gnttab_munmap(mount->gnth, priv_req->page, 1) == 0); + assert(xc_gnttab_munmap(mount->gnth, + priv_req->page, + priv_req->count) == 0); /* Get a response from the ring */ rsp_idx = mount->ring.rsp_prod_pvt++; @@ -242,7 +258,7 @@ void end_file_write(struct mount *mount, rsp->ret_val = (uint64_t)aio_return(&priv_req->aiocb); } -void dispatch_stat(struct mount *mount, struct fsif_request *req) +static void dispatch_stat(struct fs_mount *mount, struct fsif_request *req) { struct fsif_stat_response *buf; struct stat stat; @@ -251,12 +267,6 @@ void dispatch_stat(struct mount *mount, RING_IDX rsp_idx; fsif_response_t *rsp; - /* Read the request */ - buf = xc_gnttab_map_grant_ref(mount->gnth, - mount->dom_id, - req->u.fstat.gref, - PROT_WRITE); - req_id = req->id; if (req->u.fstat.fd < MAX_FDS) fd = mount->fds[req->u.fstat.fd]; @@ -272,38 +282,35 @@ void dispatch_stat(struct mount *mount, /* Stat, and create the response */ ret = fstat(fd, &stat); printf("Mode=%o, uid=%d, a_time=%ld\n", - stat.st_mode, stat.st_uid, stat.st_atime); - buf->stat_mode = stat.st_mode; - buf->stat_uid = stat.st_uid; - buf->stat_gid = stat.st_gid; + stat.st_mode, stat.st_uid, (long)stat.st_atime); + + /* Get a response from the ring */ + rsp_idx = mount->ring.rsp_prod_pvt++; + printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); + rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); + rsp->id = req_id; + rsp->fstat.stat_ret = (uint32_t)ret; + rsp->fstat.stat_mode = stat.st_mode; + rsp->fstat.stat_uid = stat.st_uid; + rsp->fstat.stat_gid = stat.st_gid; #ifdef BLKGETSIZE if (S_ISBLK(stat.st_mode)) { unsigned long sectors; if (ioctl(fd, BLKGETSIZE, §ors)) { perror("getting device size\n"); - buf->stat_size = 0; + rsp->fstat.stat_size = 0; } else - buf->stat_size = sectors << 9; + rsp->fstat.stat_size = sectors << 9; } else #endif - buf->stat_size = stat.st_size; - buf->stat_atime = stat.st_atime; - buf->stat_mtime = stat.st_mtime; - buf->stat_ctime = stat.st_ctime; - - /* Release the grant */ - assert(xc_gnttab_munmap(mount->gnth, buf, 1) == 0); - - /* Get a response from the ring */ - rsp_idx = mount->ring.rsp_prod_pvt++; - printf("Writing response at: idx=%d, id=%d\n", rsp_idx, req_id); - rsp = RING_GET_RESPONSE(&mount->ring, rsp_idx); - rsp->id = req_id; - rsp->ret_val = (uint64_t)ret; -} - - -void dispatch_truncate(struct mount *mount, struct fsif_request *req) + rsp->fstat.stat_size = stat.st_size; + rsp->fstat.stat_atime = stat.st_atime; + rsp->fstat.stat_mtime = stat.st_mtime; + rsp->fstat.stat_ctime = stat.st_ctime; +} + + +static void dispatch_truncate(struct fs_mount *mount, struct fsif_request *req) { int fd, ret; uint16_t req_id; @@ -335,7 +342,7 @@ void dispatch_truncate(struct mount *mou rsp->ret_val = (uint64_t)ret; } -void dispatch_remove(struct mount *mount, struct fsif_request *req) +static void dispatch_remove(struct fs_mount *mount, struct fsif_request *req) { char *file_name, full_path[BUFFER_SIZE]; int ret; @@ -374,7 +381,7 @@ void dispatch_remove(struct mount *mount } -void dispatch_rename(struct mount *mount, struct fsif_request *req) +static void dispatch_rename(struct fs_mount *mount, struct fsif_request *req) { char *buf, *old_file_name, *new_file_name; char old_full_path[BUFFER_SIZE], new_full_path[BUFFER_SIZE]; @@ -421,7 +428,7 @@ void dispatch_rename(struct mount *mount } -void dispatch_create(struct mount *mount, struct fsif_request *req) +static void dispatch_create(struct fs_mount *mount, struct fsif_request *req) { char *file_name, full_path[BUFFER_SIZE]; int ret; @@ -459,7 +466,17 @@ void dispatch_create(struct mount *mount else { printf("Issuing create for file: %s\n", full_path); - ret = creat(full_path, mode); + ret = get_fd(mount); + if (ret >= 0) { + int real_fd = creat(full_path, mode); + if (real_fd < 0) + ret = -1; + else + { + mount->fds[ret] = real_fd; + printf("Got FD: %d for real %d\n", ret, real_fd); + } + } } printf("Got ret %d (errno=%d)\n", ret, errno); @@ -471,7 +488,7 @@ void dispatch_create(struct mount *mount rsp->ret_val = (uint64_t)ret; } -void dispatch_list(struct mount *mount, struct fsif_request *req) +static void dispatch_list(struct fs_mount *mount, struct fsif_request *req) { char *file_name, *buf, full_path[BUFFER_SIZE]; uint32_t offset, nr_files, error_code; @@ -541,7 +558,7 @@ error_out: rsp->ret_val = ret_val; } -void dispatch_chmod(struct mount *mount, struct fsif_request *req) +static void dispatch_chmod(struct fs_mount *mount, struct fsif_request *req) { int fd, ret; RING_IDX rsp_idx; @@ -572,13 +589,13 @@ void dispatch_chmod(struct mount *mount, rsp->ret_val = (uint64_t)ret; } -void dispatch_fs_space(struct mount *mount, struct fsif_request *req) +static void dispatch_fs_space(struct fs_mount *mount, struct fsif_request *req) { char *file_name, full_path[BUFFER_SIZE]; RING_IDX rsp_idx; fsif_response_t *rsp; uint16_t req_id; - struct statfs stat; + struct statvfs stat; int64_t ret; printf("Dispatching fs space operation (gref=%d).\n", req->u.fspace.gref); @@ -596,7 +613,7 @@ void dispatch_fs_space(struct mount *mou mount->export->export_path, file_name); assert(xc_gnttab_munmap(mount->gnth, file_name, 1) == 0); printf("Issuing fs space for %s\n", full_path); - ret = statfs(full_path, &stat); + ret = statvfs(full_path, &stat); if(ret >= 0) ret = stat.f_bsize * stat.f_bfree; @@ -613,7 +630,7 @@ void dispatch_fs_space(struct mount *mou rsp->ret_val = (uint64_t)ret; } -void dispatch_file_sync(struct mount *mount, struct fsif_request *req) +static void dispatch_file_sync(struct fs_mount *mount, struct fsif_request *req) { int fd; uint16_t req_id; @@ -643,7 +660,7 @@ void dispatch_file_sync(struct mount *mo mount->ring.req_cons++; } -void end_file_sync(struct mount *mount, struct fs_request *priv_req) +static void end_file_sync(struct fs_mount *mount, struct fs_request *priv_req) { RING_IDX rsp_idx; fsif_response_t *rsp; diff -r 7affdebb7a1e -r a39913db6e51 tools/fs-back/fs-xenbus.c --- a/tools/fs-back/fs-xenbus.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/fs-back/fs-xenbus.c Thu Aug 07 11:57:34 2008 +0900 @@ -109,10 +109,11 @@ int xenbus_get_watch_fd(void) return xs_fileno(xsh); } -void xenbus_read_mount_request(struct mount *mount, char *frontend) +void xenbus_read_mount_request(struct fs_mount *mount, char *frontend) { char node[1024]; char *s; + int i; assert(xsh != NULL); #if 0 @@ -125,10 +126,18 @@ void xenbus_read_mount_request(struct mo s = xs_read(xsh, XBT_NULL, node, NULL); assert(strcmp(s, STATE_READY) == 0); free(s); - snprintf(node, sizeof(node), "%s/ring-ref", frontend); + snprintf(node, sizeof(node), "%s/ring-size", frontend); s = xs_read(xsh, XBT_NULL, node, NULL); - mount->gref = atoi(s); + mount->shared_ring_size = atoi(s); + assert(mount->shared_ring_size <= MAX_RING_SIZE); free(s); + for(i=0; i<mount->shared_ring_size; i++) + { + snprintf(node, sizeof(node), "%s/ring-ref-%d", frontend, i); + s = xs_read(xsh, XBT_NULL, node, NULL); + mount->grefs[i] = atoi(s); + free(s); + } snprintf(node, sizeof(node), "%s/event-channel", frontend); s = xs_read(xsh, XBT_NULL, node, NULL); mount->remote_evtchn = atoi(s); @@ -150,7 +159,7 @@ static int get_self_id(void) } -void xenbus_write_backend_node(struct mount *mount) +void xenbus_write_backend_node(struct fs_mount *mount) { char node[1024], backend_node[1024]; int self_id; @@ -167,7 +176,7 @@ void xenbus_write_backend_node(struct mo xs_write(xsh, XBT_NULL, node, STATE_INITIALISED, strlen(STATE_INITIALISED)); } -void xenbus_write_backend_ready(struct mount *mount) +void xenbus_write_backend_ready(struct fs_mount *mount) { char node[1024]; int self_id; diff -r 7affdebb7a1e -r a39913db6e51 tools/include/xen-sys/MiniOS/privcmd.h --- a/tools/include/xen-sys/MiniOS/privcmd.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/include/xen-sys/MiniOS/privcmd.h Thu Aug 07 11:57:34 2008 +0900 @@ -10,9 +10,7 @@ typedef struct privcmd_hypercall } privcmd_hypercall_t; typedef struct privcmd_mmap_entry { - u64 va; u64 mfn; - u64 npages; } privcmd_mmap_entry_t; #endif /* __MINIOS_PUBLIC_PRIVCMD_H__ */ diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/block-vbd.c --- a/tools/ioemu/block-vbd.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/block-vbd.c Thu Aug 07 11:57:34 2008 +0900 @@ -273,6 +273,10 @@ static BlockDriverAIOCB *vbd_aio_flush(B BDRVVbdState *s = bs->opaque; VbdAIOCB *acb = NULL; + if (s->info.mode == O_RDONLY) { + cb(opaque, 0); + return NULL; + } if (s->info.barrier == 1) { acb = vbd_aio_setup(bs, 0, NULL, 0, s->info.flush == 1 ? vbd_nop_cb : cb, opaque); diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/pass-through.c --- a/tools/ioemu/hw/pass-through.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/pass-through.c Thu Aug 07 11:57:34 2008 +0900 @@ -138,6 +138,13 @@ static int pt_msixctrl_reg_write(struct struct pt_reg_tbl *cfg_entry, uint16_t *value, uint16_t dev_value, uint16_t valid_mask); +/* pt_reg_info_tbl declaration + * - only for emulated register (either a part or whole bit). + * - for passthrough register that need special behavior (like interacting with + * other component), set emu_mask to all 0 and specify r/w func properly. + * - do NOT use ALL F for init_val, otherwise the tbl will not be registered. + */ + /* Header Type0 reg static infomation table */ static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = { /* Command reg */ @@ -564,6 +571,13 @@ static struct pt_reg_info_tbl pt_emu_reg }, }; +/* pt_reg_grp_info_tbl declaration + * - only for emulated or zero-hardwired register group. + * - for register group with dynamic size, just set grp_size to 0xFF and + * specify size_init func properly. + * - no need to specify emu_reg_tbl for zero-hardwired type. + */ + /* emul reg group static infomation table */ static const struct pt_reg_grp_info_tbl pt_emu_reg_grp_tbl[] = { /* Header Type0 reg group */ @@ -821,7 +835,7 @@ void pt_iomem_map(PCIDevice *d, int i, u assigned_device->bases[i].e_size= e_size; PT_LOG("e_phys=%08x maddr=%lx type=%d len=%d index=%d first_map=%d\n", - e_phys, assigned_device->bases[i].access.maddr, + e_phys, (unsigned long)assigned_device->bases[i].access.maddr, type, e_size, i, first_map); if ( e_size == 0 ) @@ -843,7 +857,7 @@ void pt_iomem_map(PCIDevice *d, int i, u } } - /* map only valid guest address (include 0) */ + /* map only valid guest address */ if (e_phys != -1) { /* Create new mapping */ @@ -860,7 +874,7 @@ void pt_iomem_map(PCIDevice *d, int i, u ret = remove_msix_mapping(assigned_device, i); if ( ret != 0 ) - PT_LOG("Error: remove MSX-X mmio mapping failed!\n"); + PT_LOG("Error: remove MSI-X mmio mapping failed!\n"); } } @@ -996,8 +1010,11 @@ static void pt_pci_write_config(PCIDevic int index = 0; int ret = 0; - PT_LOG("write(%x.%x): address=%04x val=0x%08x len=%d\n", - (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len); +#ifdef PT_DEBUG_PCI_CONFIG_ACCESS + PT_LOG("[%02x:%02x.%x]: address=%04x val=0x%08x len=%d\n", + pci_bus_num(d->bus), (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), + address, val, len); +#endif /* check offset range */ if (address >= 0xFF) @@ -1049,7 +1066,10 @@ static void pt_pci_write_config(PCIDevic if (reg_grp->grp_type == GRP_TYPE_HARDWIRED) { /* ignore silently */ - PT_LOG("Access to 0 Hardwired register.\n"); + PT_LOG("Access to 0 Hardwired register. " + "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n", + pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), + (d->devfn & 0x7), address, len); goto exit; } } @@ -1067,22 +1087,22 @@ static void pt_pci_write_config(PCIDevic break; } - /* check libpci error */ + /* check libpci result */ valid_mask = (0xFFFFFFFF >> ((4 - len) << 3)); if ((read_val & valid_mask) == valid_mask) { - PT_LOG("libpci read error. No emulation. " + PT_LOG("Warning: Return ALL F from libpci read. " "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n", pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7), address, len); - goto exit; } /* pass directly to libpci for passthrough type register group */ if (reg_grp_entry == NULL) goto out; - /* adjust the write value to appropriate CFC-CFF window */ + /* adjust the read and write value to appropriate CFC-CFF window */ + read_val <<= ((address & 3) << 3); val <<= ((address & 3) << 3); emul_len = len; @@ -1131,7 +1151,8 @@ static void pt_pci_write_config(PCIDevic if (ret < 0) { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Invalid write emulation " + "return value[%d]. I/O emulator exit.\n", ret); exit(1); } @@ -1186,9 +1207,6 @@ static uint32_t pt_pci_read_config(PCIDe int emul_len = 0; int ret = 0; - PT_LOG("read(%x.%x): address=%04x len=%d\n", - (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, len); - /* check offset range */ if (address >= 0xFF) { @@ -1246,15 +1264,14 @@ static uint32_t pt_pci_read_config(PCIDe break; } - /* check libpci error */ + /* check libpci result */ valid_mask = (0xFFFFFFFF >> ((4 - len) << 3)); if ((val & valid_mask) == valid_mask) { - PT_LOG("libpci read error. No emulation. " + PT_LOG("Warning: Return ALL F from libpci read. " "[%02x:%02x.%x][Offset:%02xh][Length:%d]\n", pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7), address, len); - goto exit; } /* just return the I/O device register value for @@ -1309,7 +1326,8 @@ static uint32_t pt_pci_read_config(PCIDe if (ret < 0) { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Invalid read emulation " + "return value[%d]. I/O emulator exit.\n", ret); exit(1); } @@ -1332,6 +1350,13 @@ static uint32_t pt_pci_read_config(PCIDe val >>= ((address & 3) << 3); exit: + +#ifdef PT_DEBUG_PCI_CONFIG_ACCESS + PT_LOG("[%02x:%02x.%x]: address=%04x val=0x%08x len=%d\n", + pci_bus_num(d->bus), (d->devfn >> 3) & 0x1F, (d->devfn & 0x7), + address, val, len); +#endif + return val; } @@ -1389,7 +1414,7 @@ static int pt_register_regions(struct pt return 0; } -static int pt_unregister_regions(struct pt_dev *assigned_device) +static void pt_unregister_regions(struct pt_dev *assigned_device) { int i, type, ret; uint32_t e_size; @@ -1488,7 +1513,9 @@ static int pt_bar_reg_parse( /* check 64bit BAR */ index = pt_bar_offset_to_index(reg->offset); if ((index > 0) && (index < PCI_ROM_SLOT) && - (d->config[bar_64] & PCI_BASE_ADDRESS_MEM_TYPE_64)) + ((d->config[bar_64] & (PCI_BASE_ADDRESS_SPACE | + PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == + (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64))) { region = &ptdev->bases[index-1]; if (region->bar_flag != PT_BAR_FLAG_UPPER) @@ -1502,6 +1529,13 @@ static int pt_bar_reg_parse( r = &d->io_regions[index]; if (!r->size) goto out; + + /* for ExpROM BAR */ + if (index == PCI_ROM_SLOT) + { + bar_flag = PT_BAR_FLAG_MEM; + goto out; + } /* check BAR I/O indicator */ if (d->config[reg->offset] & PCI_BASE_ADDRESS_SPACE_IO) @@ -1540,7 +1574,7 @@ static void pt_bar_mapping(struct pt_dev /* copy region address to temporary */ r_addr = r->addr; - /* clear region address in case I/O Space or Memory Space disable */ + /* need unmapping in case I/O Space or Memory Space disable */ if (((base->bar_flag == PT_BAR_FLAG_IO) && !io_enable ) || ((base->bar_flag == PT_BAR_FLAG_MEM) && !mem_enable )) r_addr = -1; @@ -1556,8 +1590,10 @@ static void pt_bar_mapping(struct pt_dev /* check overlapped address */ ret = pt_chk_bar_overlap(dev->bus, dev->devfn, r_addr, r_size); if (ret > 0) - PT_LOG("Base Address[%d] is overlapped. " - "[Address:%08xh][Size:%04xh]\n", i, r_addr, r_size); + PT_LOG("ptdev[%02x:%02x.%x][Region:%d][Address:%08xh][Size:%08xh] " + "is overlapped.\n", pci_bus_num(dev->bus), + (dev->devfn >> 3) & 0x1F, (dev->devfn & 0x7), + i, r_addr, r_size); /* check whether we need to update the mapping or not */ if (r_addr != ptdev->bases[i].e_physbase) @@ -1776,14 +1812,16 @@ static uint32_t pt_status_reg_init(struc else { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Couldn't find pt_reg_tbl for " + "Capabilities Pointer register. I/O emulator exit.\n"); exit(1); } } else { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Couldn't find pt_reg_grp_tbl for Header. " + "I/O emulator exit.\n"); exit(1); } @@ -1815,7 +1853,8 @@ static uint32_t pt_bar_reg_init(struct p if (index < 0) { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Invalid BAR index[%d]. " + "I/O emulator exit.\n", index); exit(1); } @@ -1962,9 +2001,8 @@ static uint8_t pt_msi_size_init(struct p ptdev->msi = malloc(sizeof(struct pt_msi_info)); if ( !ptdev->msi ) { - PT_LOG("error allocation pt_msi_info\n"); /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("error allocation pt_msi_info. I/O emulator exit.\n"); exit(1); } memset(ptdev->msi, 0, sizeof(struct pt_msi_info)); @@ -1983,7 +2021,8 @@ static uint8_t pt_msix_size_init(struct if (ret == -1) { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Invalid pt_msix_init return value[%d]. " + "I/O emulator exit.\n", ret); exit(1); } @@ -2060,7 +2099,8 @@ static int pt_bar_reg_read(struct pt_dev if (index < 0) { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Invalid BAR index[%d]. " + "I/O emulator exit.\n", index); exit(1); } @@ -2074,8 +2114,8 @@ static int pt_bar_reg_read(struct pt_dev bar_emu_mask = PT_BAR_IO_EMU_MASK; break; case PT_BAR_FLAG_UPPER: - *value = 0; - goto out; + bar_emu_mask = PT_BAR_ALLF; + break; default: break; } @@ -2085,7 +2125,6 @@ static int pt_bar_reg_read(struct pt_dev *value = ((*value & ~valid_emu_mask) | (cfg_entry->data & valid_emu_mask)); -out: return 0; } @@ -2201,12 +2240,13 @@ static int pt_bar_reg_write(struct pt_de uint32_t r_size = 0; int index = 0; - /* get BAR index */ + /* get BAR index */ index = pt_bar_offset_to_index(reg->offset); if (index < 0) { /* exit I/O emulator */ - PT_LOG("I/O emulator exit()\n"); + PT_LOG("Internal error: Invalid BAR index[%d]. " + "I/O emulator exit.\n", index); exit(1); } @@ -2216,89 +2256,113 @@ static int pt_bar_reg_write(struct pt_de /* align resource size (memory type only) */ PT_GET_EMUL_SIZE(base->bar_flag, r_size); - /* check guest write value */ - if (*value == PT_BAR_ALLF) - { - /* set register with resource size alligned to page size */ - cfg_entry->data = ~(r_size - 1); - /* avoid writing ALL F to I/O device register */ - *value = dev_value; - } - else - { - /* set emulate mask and read-only mask depend on BAR flag */ - switch (ptdev->bases[index].bar_flag) - { - case PT_BAR_FLAG_MEM: - bar_emu_mask = PT_BAR_MEM_EMU_MASK; - bar_ro_mask = PT_BAR_MEM_RO_MASK; - break; - case PT_BAR_FLAG_IO: - new_addr = *value; - last_addr = new_addr + r_size - 1; + /* set emulate mask and read-only mask depend on BAR flag */ + switch (ptdev->bases[index].bar_flag) + { + case PT_BAR_FLAG_MEM: + bar_emu_mask = PT_BAR_MEM_EMU_MASK; + bar_ro_mask = PT_BAR_MEM_RO_MASK | (r_size - 1); + break; + case PT_BAR_FLAG_IO: + bar_emu_mask = PT_BAR_IO_EMU_MASK; + bar_ro_mask = PT_BAR_IO_RO_MASK | (r_size - 1); + break; + case PT_BAR_FLAG_UPPER: + bar_emu_mask = PT_BAR_ALLF; + bar_ro_mask = 0; /* all upper 32bit are R/W */ + break; + default: + break; + } + + /* modify emulate register */ + writable_mask = bar_emu_mask & ~bar_ro_mask & valid_mask; + cfg_entry->data = ((*value & writable_mask) | + (cfg_entry->data & ~writable_mask)); + + /* check whether we need to update the virtual region address or not */ + switch (ptdev->bases[index].bar_flag) + { + case PT_BAR_FLAG_MEM: + /* nothing to do */ + break; + case PT_BAR_FLAG_IO: + new_addr = cfg_entry->data; + last_addr = new_addr + r_size - 1; + /* check invalid address */ + if (last_addr <= new_addr || !new_addr || last_addr >= 0x10000) + { /* check 64K range */ - if (last_addr <= new_addr || !new_addr || last_addr >= 0x10000) + if ((last_addr >= 0x10000) && + (cfg_entry->data != (PT_BAR_ALLF & ~bar_ro_mask))) { PT_LOG("Guest attempt to set Base Address over the 64KB. " - "[%02x:%02x.%x][Offset:%02xh][Range:%08xh-%08xh]\n", + "[%02x:%02x.%x][Offset:%02xh][Address:%08xh][Size:%08xh]\n", pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7), - reg->offset, new_addr, last_addr); - /* just remove mapping */ - r->addr = -1; - goto exit; + reg->offset, new_addr, r_size); } - bar_emu_mask = PT_BAR_IO_EMU_MASK; - bar_ro_mask = PT_BAR_IO_RO_MASK; - break; - case PT_BAR_FLAG_UPPER: - if (*value) + /* just remove mapping */ + r->addr = -1; + goto exit; + } + break; + case PT_BAR_FLAG_UPPER: + if (cfg_entry->data) + { + if (cfg_entry->data != (PT_BAR_ALLF & ~bar_ro_mask)) { PT_LOG("Guest attempt to set high MMIO Base Address. " - "Ignore mapping. " - "[%02x:%02x.%x][Offset:%02xh][High Address:%08xh]\n", + "Ignore mapping. " + "[%02x:%02x.%x][Offset:%02xh][High Address:%08xh]\n", pci_bus_num(d->bus), ((d->devfn >> 3) & 0x1F), (d->devfn & 0x7), - reg->offset, *value); - /* clear lower address */ - d->io_regions[index-1].addr = -1; + reg->offset, cfg_entry->data); } - else + /* clear lower address */ + d->io_regions[index-1].addr = -1; + } + else + { + /* find lower 32bit BAR */ + prev_offset = (reg->offset - 4); + reg_grp_entry = pt_find_reg_grp(ptdev, prev_offset); + if (reg_grp_entry) { - /* find lower 32bit BAR */ - prev_offset = (reg->offset - 4); - reg_grp_entry = pt_find_reg_grp(ptdev, prev_offset); - if (reg_grp_entry) - { - reg_entry = pt_find_reg(reg_grp_entry, prev_offset); - if (reg_entry) - /* restore lower address */ - d->io_regions[index-1].addr = reg_entry->data; - else - return -1; - } + reg_entry = pt_find_reg(reg_grp_entry, prev_offset); + if (reg_entry) + /* restore lower address */ + d->io_regions[index-1].addr = reg_entry->data; else return -1; } - cfg_entry->data = 0; - r->addr = -1; - goto exit; - } - - /* modify emulate register */ - writable_mask = bar_emu_mask & ~bar_ro_mask & valid_mask; - cfg_entry->data = ((*value & writable_mask) | - (cfg_entry->data & ~writable_mask)); - /* update the corresponding virtual region address */ - r->addr = cfg_entry->data; - - /* create value for writing to I/O device register */ - throughable_mask = ~bar_emu_mask & valid_mask; - *value = ((*value & throughable_mask) | - (dev_value & ~throughable_mask)); - } + else + return -1; + } + + /* always keep the emulate register value to 0, + * because hvmloader does not support high MMIO for now. + */ + cfg_entry->data = 0; + + /* never mapping the 'empty' upper region, + * because we'll do it enough for the lower region. + */ + r->addr = -1; + goto exit; + default: + break; + } + + /* update the corresponding virtual region address */ + r->addr = cfg_entry->data; exit: + /* create value for writing to I/O device register */ + throughable_mask = ~bar_emu_mask & valid_mask; + *value = ((*value & throughable_mask) | + (dev_value & ~throughable_mask)); + return 0; } @@ -2314,6 +2378,8 @@ static int pt_exp_rom_bar_reg_write(stru uint32_t writable_mask = 0; uint32_t throughable_mask = 0; uint32_t r_size = 0; + uint32_t bar_emu_mask = 0; + uint32_t bar_ro_mask = 0; r = &d->io_regions[PCI_ROM_SLOT]; r_size = r->size; @@ -2321,28 +2387,22 @@ static int pt_exp_rom_bar_reg_write(stru /* align memory type resource size */ PT_GET_EMUL_SIZE(base->bar_flag, r_size); - /* check guest write value */ - if (*value == PT_BAR_ALLF) - { - /* set register with resource size alligned to page size */ - cfg_entry->data = ~(r_size - 1); - /* avoid writing ALL F to I/O device register */ - *value = dev_value; - } - else - { - /* modify emulate register */ - writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; - cfg_entry->data = ((*value & writable_mask) | - (cfg_entry->data & ~writable_mask)); - /* update the corresponding virtual region address */ - r->addr = cfg_entry->data; - - /* create value for writing to I/O device register */ - throughable_mask = ~reg->emu_mask & valid_mask; - *value = ((*value & throughable_mask) | - (dev_value & ~throughable_mask)); - } + /* set emulate mask and read-only mask */ + bar_emu_mask = reg->emu_mask; + bar_ro_mask = reg->ro_mask | (r_size - 1); + + /* modify emulate register */ + writable_mask = bar_emu_mask & ~bar_ro_mask & valid_mask; + cfg_entry->data = ((*value & writable_mask) | + (cfg_entry->data & ~writable_mask)); + + /* update the corresponding virtual region address */ + r->addr = cfg_entry->data; + + /* create value for writing to I/O device register */ + throughable_mask = ~bar_emu_mask & valid_mask; + *value = ((*value & throughable_mask) | + (dev_value & ~throughable_mask)); return 0; } @@ -2483,8 +2543,6 @@ static int pt_msgctrl_reg_write(struct p uint16_t throughable_mask = 0; uint16_t old_ctrl = cfg_entry->data; PCIDevice *pd = (PCIDevice *)ptdev; - - PT_LOG("[before] dev_val:%xh wr_val:%xh\n", dev_value, *value); /* Currently no support for multi-vector */ if ((*value & PCI_MSI_FLAGS_QSIZE) != 0x0) @@ -2527,8 +2585,6 @@ static int pt_msgctrl_reg_write(struct p else ptdev->msi->flags &= ~PCI_MSI_FLAGS_ENABLE; - PT_LOG("[after] wr_val:%xh\n", *value); - return 0; } @@ -2541,8 +2597,6 @@ static int pt_msgaddr32_reg_write(struct uint32_t writable_mask = 0; uint32_t throughable_mask = 0; uint32_t old_addr = cfg_entry->data; - - PT_LOG("[before] dev_val:%xh wr_val:%xh\n", dev_value, *value); /* modify emulate register */ writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; @@ -2564,8 +2618,6 @@ static int pt_msgaddr32_reg_write(struct pt_msi_update(ptdev); } - PT_LOG("[after] wr_val:%xh\n", *value); - return 0; } @@ -2578,8 +2630,6 @@ static int pt_msgaddr64_reg_write(struct uint32_t writable_mask = 0; uint32_t throughable_mask = 0; uint32_t old_addr = cfg_entry->data; - - PT_LOG("[before] dev_val:%xh wr_val:%xh\n", dev_value, *value); /* check whether the type is 64 bit or not */ if (!(ptdev->msi->flags & PCI_MSI_FLAGS_64BIT)) @@ -2609,8 +2659,6 @@ static int pt_msgaddr64_reg_write(struct pt_msi_update(ptdev); } - PT_LOG("[after] wr_val:%xh\n", *value); - return 0; } @@ -2627,8 +2675,6 @@ static int pt_msgdata_reg_write(struct p uint32_t flags = ptdev->msi->flags; uint32_t offset = reg->offset; - PT_LOG("[before] dev_val:%xh wr_val:%xh\n", dev_value, *value); - /* check the offset whether matches the type or not */ if (!((offset == PCI_MSI_DATA_64) && (flags & PCI_MSI_FLAGS_64BIT)) && !((offset == PCI_MSI_DATA_32) && !(flags & PCI_MSI_FLAGS_64BIT))) @@ -2658,8 +2704,6 @@ static int pt_msgdata_reg_write(struct p pt_msi_update(ptdev); } - PT_LOG("[after] wr_val:%xh\n", *value); - return 0; } @@ -2672,8 +2716,6 @@ static int pt_msixctrl_reg_write(struct uint16_t writable_mask = 0; uint16_t throughable_mask = 0; uint16_t old_ctrl = cfg_entry->data; - - PT_LOG("[before] dev_val:%xh wr_val:%xh\n", dev_value, *value); /* modify emulate register */ writable_mask = reg->emu_mask & ~reg->ro_mask & valid_mask; @@ -2691,8 +2733,6 @@ static int pt_msixctrl_reg_write(struct pt_msix_update(ptdev); ptdev->msix->enabled = !!(*value & PCI_MSIX_ENABLE); - - PT_LOG("[after] wr_val:%xh\n", *value); return 0; } @@ -2785,8 +2825,7 @@ struct pt_dev * register_real_device(PCI int pirq = pci_dev->irq; machine_irq = pci_dev->irq; - rc = xc_physdev_map_pirq(xc_handle, domid, MAP_PIRQ_TYPE_GSI, - machine_irq, &pirq); + rc = xc_physdev_map_pirq(xc_handle, domid, machine_irq, &pirq); if ( rc ) { diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/pass-through.h --- a/tools/ioemu/hw/pass-through.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/pass-through.h Thu Aug 07 11:57:34 2008 +0900 @@ -47,12 +47,20 @@ /* because the current version of libpci (2.2.0) doesn't define these ID, * so we define Capability ID here. */ +#ifndef PCI_CAP_ID_HOTPLUG /* SHPC Capability List Item reg group */ #define PCI_CAP_ID_HOTPLUG 0x0C +#endif + +#ifndef PCI_CAP_ID_SSVID /* Subsystem ID and Subsystem Vendor ID Capability List Item reg group */ #define PCI_CAP_ID_SSVID 0x0D +#endif + +#ifndef PCI_MSI_FLAGS_MASK_BIT /* interrupt masking & reporting supported */ #define PCI_MSI_FLAGS_MASK_BIT 0x0100 +#endif #define PT_INVALID_REG 0xFFFFFFFF /* invalid register value */ #define PT_BAR_ALLF 0xFFFFFFFF /* BAR ALLF value */ diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/pc.c --- a/tools/ioemu/hw/pc.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/pc.c Thu Aug 07 11:57:34 2008 +0900 @@ -30,9 +30,6 @@ #define VGABIOS_FILENAME "vgabios.bin" #define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" #define LINUX_BOOT_FILENAME "linux_boot.bin" - -/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ -#define ACPI_DATA_SIZE 0x10000 static fdctrl_t *floppy_controller; static RTCState *rtc_state; @@ -542,6 +539,7 @@ static void load_linux(const char *kerne uint16_t seg[6]; uint16_t real_seg; int setup_size, kernel_size, initrd_size, cmdline_size; + unsigned long end_low_ram; uint32_t initrd_max; uint8_t header[1024]; target_phys_addr_t real_addr, reloc_prot_addr, prot_addr, cmdline_addr, initrd_addr; @@ -595,15 +593,14 @@ static void load_linux(const char *kerne (size_t)cmdline_addr, (size_t)prot_addr); + /* Special pages are placed at end of low RAM: pick an arbitrary one and + * subtract a suitably large amount of padding (64kB) to skip BIOS data. */ + xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &end_low_ram); + end_low_ram = (end_low_ram << 12) - (64*1024); + /* highest address for loading the initrd */ - if (protocol >= 0x203) - initrd_max = ldl_p(header+0x22c); - else - initrd_max = 0x37ffffff; - - if (initrd_max >= ram_size-ACPI_DATA_SIZE) - initrd_max = ram_size-ACPI_DATA_SIZE-1; - + initrd_max = (protocol >= 0x203) ? ldl_p(header+0x22c) : 0x37ffffff; + initrd_max = MIN(initrd_max, (uint32_t)end_low_ram); /* kernel command line */ ncmdline = strlen(kernel_cmdline); diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/pci.c --- a/tools/ioemu/hw/pci.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/pci.c Thu Aug 07 11:57:34 2008 +0900 @@ -664,9 +664,10 @@ int pt_chk_bar_overlap(PCIBus *bus, int r = &devices->io_regions[j]; if ((addr < (r->addr + r->size)) && ((addr + size) > r->addr)) { - printf("Overlapped to device[%02x:%02x.%x] region:%d addr:%08x" - " size:%08x\n", bus->bus_num, (devices->devfn >> 3) & 0x1F, - (devices->devfn & 0x7), j, r->addr, r->size); + printf("Overlapped to device[%02x:%02x.%x][Region:%d]" + "[Address:%08xh][Size:%08xh]\n", bus->bus_num, + (devices->devfn >> 3) & 0x1F, (devices->devfn & 0x7), + j, r->addr, r->size); ret = 1; goto out; } diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/pt-msi.c --- a/tools/ioemu/hw/pt-msi.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/pt-msi.c Thu Aug 07 11:57:34 2008 +0900 @@ -37,8 +37,7 @@ int pt_msi_setup(struct pt_dev *dev) return -1; } - if ( xc_physdev_map_pirq_msi(xc_handle, domid, MAP_PIRQ_TYPE_MSI, - AUTO_ASSIGN, &pirq, + if ( xc_physdev_map_pirq_msi(xc_handle, domid, AUTO_ASSIGN, &pirq, dev->pci_dev->dev << 3 | dev->pci_dev->func, dev->pci_dev->bus, 0, 1) ) { @@ -120,8 +119,7 @@ static int pt_msix_update_one(struct pt_ /* Check if this entry is already mapped */ if ( entry->pirq == -1 ) { - ret = xc_physdev_map_pirq_msi(xc_handle, domid, MAP_PIRQ_TYPE_MSI, - AUTO_ASSIGN, &pirq, + ret = xc_physdev_map_pirq_msi(xc_handle, domid, AUTO_ASSIGN, &pirq, dev->pci_dev->dev << 3 | dev->pci_dev->func, dev->pci_dev->bus, entry_nr, 0); if ( ret ) diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/serial.c --- a/tools/ioemu/hw/serial.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/serial.c Thu Aug 07 11:57:34 2008 +0900 @@ -728,7 +728,6 @@ static int serial_load(QEMUFile *f, void qemu_get_8s(f,&s->lsr); qemu_get_8s(f,&s->msr); qemu_get_8s(f,&s->scr); - qemu_get_8s(f,&s->fcr); if (version_id >= 2) qemu_get_8s(f,&fcr); diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/hw/vga.c --- a/tools/ioemu/hw/vga.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/hw/vga.c Thu Aug 07 11:57:34 2008 +0900 @@ -1548,8 +1548,8 @@ static void vga_draw_graphic(VGAState *s } else { /* ENODATA just means we have changed mode and will succeed * next time */ - if (err != -ENODATA) - fprintf(stderr, "track_dirty_vram(%lx, %lx) failed (%d)\n", s->lfb_addr + y, npages, err); + if (errno != ENODATA) + fprintf(stderr, "track_dirty_vram(%lx, %lx) failed (%d, %d)\n", s->lfb_addr + y, npages, err, errno); } } diff -r 7affdebb7a1e -r a39913db6e51 tools/ioemu/vl.c --- a/tools/ioemu/vl.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/ioemu/vl.c Thu Aug 07 11:57:34 2008 +0900 @@ -7136,8 +7136,10 @@ int main(int argc, char **argv) sigaddset(&set, aio_sig_num); sigprocmask(SIG_BLOCK, &set, NULL); } +#endif QEMU_LIST_INIT (&vm_change_state_head); +#ifndef CONFIG_STUBDOM #ifndef _WIN32 { struct sigaction act; diff -r 7affdebb7a1e -r a39913db6e51 tools/libaio/src/Makefile --- a/tools/libaio/src/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libaio/src/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -1,7 +1,7 @@ XEN_ROOT = ../../.. XEN_ROOT = ../../.. include $(XEN_ROOT)/tools/Rules.mk -prefix=/usr +prefix=$(PREFIX) includedir=$(prefix)/include libdir=$(prefix)/lib diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_dom_boot.c --- a/tools/libxc/xc_dom_boot.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_dom_boot.c Thu Aug 07 11:57:34 2008 +0900 @@ -4,7 +4,7 @@ * This is the code which actually boots a fresh * prepared domain image as xen guest domain. * - * ==> this is the only domain bilder code piece + * ==> this is the only domain builder code piece * where xen hypercalls are allowed <== * * This code is licenced under the GPL. @@ -153,7 +153,7 @@ void *xc_dom_boot_domU_map(struct xc_dom int page_shift = XC_DOM_PAGE_SHIFT(dom); privcmd_mmap_entry_t *entries; void *ptr; - int i, rc; + int i; int err; entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t)); @@ -165,9 +165,13 @@ void *xc_dom_boot_domU_map(struct xc_dom return NULL; } - ptr = mmap(NULL, count << page_shift, PROT_READ | PROT_WRITE, - MAP_SHARED, dom->guest_xc, 0); - if ( ptr == MAP_FAILED ) + for ( i = 0; i < count; i++ ) + entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); + + ptr = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid, + count << page_shift, PROT_READ | PROT_WRITE, 1 << page_shift, + entries, count); + if ( ptr == NULL ) { err = errno; xc_dom_panic(XC_INTERNAL_ERROR, @@ -177,22 +181,6 @@ void *xc_dom_boot_domU_map(struct xc_dom return NULL; } - for ( i = 0; i < count; i++ ) - { - entries[i].va = (uintptr_t) ptr + (i << page_shift); - entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); - entries[i].npages = 1; - } - - rc = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid, - entries, count); - if ( rc < 0 ) - { - xc_dom_panic(XC_INTERNAL_ERROR, - "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn - " [xenctl, rc=%d]\n", __FUNCTION__, pfn, count, rc); - return NULL; - } return ptr; } diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_domain_save.c --- a/tools/libxc/xc_domain_save.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_domain_save.c Thu Aug 07 11:57:34 2008 +0900 @@ -568,16 +568,19 @@ static xen_pfn_t *xc_map_m2p(int xc_hand unsigned long m2p_chunks, m2p_size; xen_pfn_t *m2p; xen_pfn_t *extent_start; - int i, rc; - + int i; + + m2p = NULL; m2p_size = M2P_SIZE(max_mfn); m2p_chunks = M2P_CHUNKS(max_mfn); xmml.max_extents = m2p_chunks; - if ( !(extent_start = malloc(m2p_chunks * sizeof(xen_pfn_t))) ) + + extent_start = calloc(m2p_chunks, sizeof(xen_pfn_t)); + if ( !extent_start ) { ERROR("failed to allocate space for m2p mfns"); - return NULL; + goto err0; } set_xen_guest_handle(xmml.extent_start, extent_start); @@ -585,41 +588,36 @@ static xen_pfn_t *xc_map_m2p(int xc_hand (xmml.nr_extents != m2p_chunks) ) { ERROR("xc_get_m2p_mfns"); - return NULL; - } - - if ( (m2p = mmap(NULL, m2p_size, prot, - MAP_SHARED, xc_handle, 0)) == MAP_FAILED ) - { - ERROR("failed to mmap m2p"); - return NULL; - } - - if ( !(entries = malloc(m2p_chunks * sizeof(privcmd_mmap_entry_t))) ) + goto err1; + } + + entries = calloc(m2p_chunks, sizeof(privcmd_mmap_entry_t)); + if (entries == NULL) { ERROR("failed to allocate space for mmap entries"); - return NULL; + goto err1; } for ( i = 0; i < m2p_chunks; i++ ) - { - entries[i].va = (unsigned long)(((void *)m2p) + (i * M2P_CHUNK_SIZE)); entries[i].mfn = extent_start[i]; - entries[i].npages = M2P_CHUNK_SIZE >> PAGE_SHIFT; - } - - if ( (rc = xc_map_foreign_ranges(xc_handle, DOMID_XEN, - entries, m2p_chunks)) < 0 ) - { - ERROR("xc_mmap_foreign_ranges failed (rc = %d)", rc); - return NULL; + + m2p = xc_map_foreign_ranges(xc_handle, DOMID_XEN, + m2p_size, prot, M2P_CHUNK_SIZE, + entries, m2p_chunks); + if (m2p == NULL) + { + ERROR("xc_mmap_foreign_ranges failed"); + goto err2; } m2p_mfn0 = entries[0].mfn; +err2: + free(entries); +err1: free(extent_start); - free(entries); - + +err0: return m2p; } diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_hvm_build.c Thu Aug 07 11:57:34 2008 +0900 @@ -115,42 +115,32 @@ static int loadelfimage( struct elf_binary *elf, int xch, uint32_t dom, unsigned long *parray) { privcmd_mmap_entry_t *entries = NULL; - int pages = (elf->pend - elf->pstart + PAGE_SIZE - 1) >> PAGE_SHIFT; + size_t pages = (elf->pend - elf->pstart + PAGE_SIZE - 1) >> PAGE_SHIFT; int i, rc = -1; /* Map address space for initial elf image. */ - entries = malloc(pages * sizeof(privcmd_mmap_entry_t)); + entries = calloc(pages, sizeof(privcmd_mmap_entry_t)); if ( entries == NULL ) goto err; - elf->dest = mmap(NULL, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, - MAP_SHARED, xch, 0); - if ( elf->dest == MAP_FAILED ) - goto err; for ( i = 0; i < pages; i++ ) - { - entries[i].va = (uintptr_t)elf->dest + (i << PAGE_SHIFT); entries[i].mfn = parray[(elf->pstart >> PAGE_SHIFT) + i]; - entries[i].npages = 1; - } - - rc = xc_map_foreign_ranges(xch, dom, entries, pages); - if ( rc < 0 ) + + elf->dest = xc_map_foreign_ranges( + xch, dom, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 1 << PAGE_SHIFT, + entries, pages); + if ( elf->dest == NULL ) goto err; /* Load the initial elf image. */ elf_load_binary(elf); rc = 0; + munmap(elf->dest, pages << PAGE_SHIFT); + elf->dest = NULL; + err: - if ( elf->dest ) - { - munmap(elf->dest, pages << PAGE_SHIFT); - elf->dest = NULL; - } - - if ( entries ) - free(entries); + free(entries); return rc; } @@ -239,7 +229,7 @@ static int setup_guest(int xc_handle, if ( ((count | cur_pages) & (SUPERPAGE_NR_PFNS - 1)) == 0 ) { long done; - xen_pfn_t sp_extents[2048 >> SUPERPAGE_PFN_SHIFT]; + xen_pfn_t sp_extents[count >> SUPERPAGE_PFN_SHIFT]; struct xen_memory_reservation sp_req = { .nr_extents = count >> SUPERPAGE_PFN_SHIFT, .extent_order = SUPERPAGE_PFN_SHIFT, diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_linux.c --- a/tools/libxc/xc_linux.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_linux.c Thu Aug 07 11:57:34 2008 +0900 @@ -118,16 +118,41 @@ void *xc_map_foreign_range(int xc_handle return addr; } -int xc_map_foreign_ranges(int xc_handle, uint32_t dom, - privcmd_mmap_entry_t *entries, int nr) +void *xc_map_foreign_ranges(int xc_handle, uint32_t dom, + size_t size, int prot, size_t chunksize, + privcmd_mmap_entry_t entries[], int nentries) { privcmd_mmap_t ioctlx; - - ioctlx.num = nr; + int i, rc; + void *addr; + + addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0); + if ( addr == MAP_FAILED ) + goto mmap_failed; + + for ( i = 0; i < nentries; i++ ) + { + entries[i].va = (unsigned long)addr + (i * chunksize); + entries[i].npages = chunksize >> PAGE_SHIFT; + } + + ioctlx.num = nentries; ioctlx.dom = dom; ioctlx.entry = entries; - return ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx); + rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx); + if ( rc ) + goto ioctl_failed; + + return addr; + +ioctl_failed: + rc = munmap(addr, size); + if ( rc == -1 ) + ERROR("%s: error in error path\n", __FUNCTION__); + +mmap_failed: + return NULL; } static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data) diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_minios.c --- a/tools/libxc/xc_minios.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_minios.c Thu Aug 07 11:57:34 2008 +0900 @@ -15,6 +15,7 @@ #include <os.h> #include <mm.h> #include <lib.h> +#include <gntmap.h> #include <events.h> #include <wait.h> #include <sys/mman.h> @@ -76,16 +77,30 @@ void *xc_map_foreign_range(int xc_handle return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, 0, pt_prot); } -int xc_map_foreign_ranges(int xc_handle, uint32_t dom, - privcmd_mmap_entry_t *entries, int nr) -{ - int i; - for (i = 0; i < nr; i++) { - unsigned long mfn = entries[i].mfn; - do_map_frames(entries[i].va, &mfn, entries[i].npages, 0, 1, dom, 0, L1_PROT); - } - return 0; -} +void *xc_map_foreign_ranges(int xc_handle, uint32_t dom, + size_t size, int prot, size_t chunksize, + privcmd_mmap_entry_t entries[], int nentries) +{ + unsigned long mfns[size / PAGE_SIZE]; + int i, j, n; + unsigned long pt_prot = 0; +#ifdef __ia64__ + /* TODO */ +#else + if (prot & PROT_READ) + pt_prot = L1_PROT_RO; + if (prot & PROT_WRITE) + pt_prot = L1_PROT; +#endif + + n = 0; + for (i = 0; i < nentries; i++) + for (j = 0; j < chunksize / PAGE_SIZE; j++) + mfns[n++] = entries[i].mfn + j; + + return map_frames_ex(mfns, n, 1, 0, 1, dom, 0, pt_prot); +} + int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall) { @@ -102,8 +117,8 @@ int do_xen_hypercall(int xc_handle, priv errno = -ret; return -1; } - if (call.result < 0) { - errno = -call.result; + if ((long) call.result < 0) { + errno = - (long) call.result; return -1; } return call.result; @@ -244,8 +259,11 @@ int xc_evtchn_unbind(int xce_handle, evt files[xce_handle].evtchn.ports[i].port = -1; break; } - if (i == MAX_EVTCHN_PORTS) + if (i == MAX_EVTCHN_PORTS) { printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, xce_handle); + errno = -EINVAL; + return -1; + } files[xce_handle].evtchn.ports[i].bound = 0; unbind_evtchn(port); return 0; @@ -278,18 +296,24 @@ evtchn_port_or_error_t xc_evtchn_pending { int i; unsigned long flags; + evtchn_port_t ret = -1; + local_irq_save(flags); + files[xce_handle].read = 0; for (i = 0; i < MAX_EVTCHN_PORTS; i++) { - evtchn_port_t port = files[xce_handle].evtchn.ports[i].port; - if (port != -1 && files[xce_handle].evtchn.ports[i].pending) { - files[xce_handle].evtchn.ports[i].pending = 0; - local_irq_restore(flags); - return port; - } - } - files[xce_handle].read = 0; + evtchn_port_t port = files[xce_handle].evtchn.ports[i].port; + if (port != -1 && files[xce_handle].evtchn.ports[i].pending) { + if (ret == -1) { + ret = port; + files[xce_handle].evtchn.ports[i].pending = 0; + } else { + files[xce_handle].read = 1; + break; + } + } + } local_irq_restore(flags); - return -1; + return ret; } int xc_evtchn_unmask(int xce_handle, evtchn_port_t port) @@ -304,6 +328,88 @@ void discard_file_cache(int fd, int flus if (flush) fsync(fd); } + +int xc_gnttab_open(void) +{ + int xcg_handle; + xcg_handle = alloc_fd(FTYPE_GNTMAP); + gntmap_init(&files[xcg_handle].gntmap); + return xcg_handle; +} + +int xc_gnttab_close(int xcg_handle) +{ + gntmap_fini(&files[xcg_handle].gntmap); + files[xcg_handle].type = FTYPE_NONE; + return 0; +} + +void *xc_gnttab_map_grant_ref(int xcg_handle, + uint32_t domid, + uint32_t ref, + int prot) +{ + return gntmap_map_grant_refs(&files[xcg_handle].gntmap, + 1, + &domid, 0, + &ref, + prot & PROT_WRITE); +} + +void *xc_gnttab_map_grant_refs(int xcg_handle, + uint32_t count, + uint32_t *domids, + uint32_t *refs, + int prot) +{ + return gntmap_map_grant_refs(&files[xcg_handle].gntmap, + count, + domids, 1, + refs, + prot & PROT_WRITE); +} + +void *xc_gnttab_map_domain_grant_refs(int xcg_handle, + uint32_t count, + uint32_t domid, + uint32_t *refs, + int prot) +{ + return gntmap_map_grant_refs(&files[xcg_handle].gntmap, + count, + &domid, 0, + refs, + prot & PROT_WRITE); +} + +int xc_gnttab_munmap(int xcg_handle, + void *start_address, + uint32_t count) +{ + int ret; + ret = gntmap_munmap(&files[xcg_handle].gntmap, + (unsigned long) start_address, + count); + if (ret < 0) { + errno = -ret; + return -1; + } + return ret; +} + +int xc_gnttab_set_max_grants(int xcg_handle, + uint32_t count) +{ + int ret; + ret = gntmap_set_max_grants(&files[xcg_handle].gntmap, + count); + if (ret < 0) { + errno = -ret; + return -1; + } + return ret; +} + /* * Local variables: * mode: C diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_netbsd.c --- a/tools/libxc/xc_netbsd.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_netbsd.c Thu Aug 07 11:57:34 2008 +0900 @@ -11,7 +11,6 @@ #include "xc_private.h" -#include <xen/memory.h> #include <xen/sys/evtchn.h> #include <unistd.h> #include <fcntl.h> @@ -114,22 +113,42 @@ void *xc_map_foreign_range(int xc_handle return addr; } -int xc_map_foreign_ranges(int xc_handle, uint32_t dom, - privcmd_mmap_entry_t *entries, int nr) -{ - privcmd_mmap_t ioctlx; - int err; - - ioctlx.num = nr; - ioctlx.dom = dom; - ioctlx.entry = entries; - - err = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx); - if (err == 0) - return 0; - else - return -errno; -} +void *xc_map_foreign_ranges(int xc_handle, uint32_t dom, + size_t size, int prot, size_t chunksize, + privcmd_mmap_entry_t entries[], int nentries) +{ + privcmd_mmap_t ioctlx; + int i, rc; + void *addr; + + addr = mmap(NULL, size, prot, MAP_ANON | MAP_SHARED, -1, 0); + if (addr == MAP_FAILED) + goto mmap_failed; + + for (i = 0; i < nentries; i++) { + entries[i].va = (uintptr_t)addr + (i * chunksize); + entries[i].npages = chunksize >> PAGE_SHIFT; + } + + ioctlx.num = nentries; + ioctlx.dom = dom; + ioctlx.entry = entries; + + rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx); + if (rc) + goto ioctl_failed; + + return addr; + +ioctl_failed: + rc = munmap(addr, size); + if (rc == -1) + ERROR("%s: error in error path\n", __FUNCTION__); + +mmap_failed: + return NULL; +} + static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data) { diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_physdev.c --- a/tools/libxc/xc_physdev.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_physdev.c Thu Aug 07 11:57:34 2008 +0900 @@ -22,7 +22,6 @@ int xc_physdev_pci_access_modify(int xc_ int xc_physdev_map_pirq(int xc_handle, int domid, - int type, int index, int *pirq) { @@ -33,7 +32,7 @@ int xc_physdev_map_pirq(int xc_handle, return -EINVAL; map.domid = domid; - map.type = type; + map.type = MAP_PIRQ_TYPE_GSI; map.index = index; map.pirq = *pirq; @@ -47,7 +46,6 @@ int xc_physdev_map_pirq(int xc_handle, int xc_physdev_map_pirq_msi(int xc_handle, int domid, - int type, int index, int *pirq, int devfn, @@ -62,7 +60,7 @@ int xc_physdev_map_pirq_msi(int xc_handl return -EINVAL; map.domid = domid; - map.type = type; + map.type = MAP_PIRQ_TYPE_MSI; map.index = index; map.pirq = *pirq; map.msi_info.devfn = devfn; diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_private.h --- a/tools/libxc/xc_private.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_private.h Thu Aug 07 11:57:34 2008 +0900 @@ -184,8 +184,9 @@ static inline int do_sysctl(int xc_handl return ret; } -int xc_map_foreign_ranges(int xc_handle, uint32_t dom, - privcmd_mmap_entry_t *entries, int nr); +void *xc_map_foreign_ranges(int xc_handle, uint32_t dom, + size_t size, int prot, size_t chunksize, + privcmd_mmap_entry_t entries[], int nentries); void *map_domain_va_core(unsigned long domfd, int cpu, void *guest_va, vcpu_guest_context_any_t *ctxt); diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xc_solaris.c --- a/tools/libxc/xc_solaris.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xc_solaris.c Thu Aug 07 11:57:34 2008 +0900 @@ -109,17 +109,40 @@ void *xc_map_foreign_range(int xc_handle return addr; } -int xc_map_foreign_ranges(int xc_handle, uint32_t dom, - privcmd_mmap_entry_t *entries, int nr) +void *xc_map_foreign_ranges(int xc_handle, uint32_t dom, + size_t size, int prot, size_t chunksize, + privcmd_mmap_entry_t entries[], int nentries) { privcmd_mmap_t ioctlx; - - ioctlx.num = nr; + int i, rc; + void *addr; + + addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0); + if (addr == MAP_FAILED) + goto mmap_failed; + + for (i = 0; i < nentries; i++) { + entries[i].va = (uintptr_t)addr + (i * chunksize); + entries[i].npages = chunksize >> PAGE_SHIFT; + } + + ioctlx.num = nentries; ioctlx.dom = dom; ioctlx.entry = entries; - return ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx); -} + rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx); + if (rc) + goto ioctl_failed; + +ioctl_failed: + rc = munmap(addr, size); + if (rc == -1) + ERROR("%s: error in error path\n", __FUNCTION__); + +mmap_failed: + return NULL; +} + static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data) { diff -r 7affdebb7a1e -r a39913db6e51 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/libxc/xenctrl.h Thu Aug 07 11:57:34 2008 +0900 @@ -907,13 +907,11 @@ int xc_gnttab_set_max_grants(int xcg_han int xc_physdev_map_pirq(int xc_handle, int domid, - int type, int index, int *pirq); int xc_physdev_map_pirq_msi(int xc_handle, int domid, - int type, int index, int *pirq, int devfn, diff -r 7affdebb7a1e -r a39913db6e51 tools/pygrub/src/pygrub --- a/tools/pygrub/src/pygrub Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/pygrub/src/pygrub Thu Aug 07 11:57:34 2008 +0900 @@ -21,7 +21,7 @@ import curses, _curses, curses.wrapper, import curses, _curses, curses.wrapper, curses.textpad, curses.ascii import getopt -sys.path = [ '/usr/lib/python' ] + sys.path +sys.path = [ '/usr/lib/python', '/usr/lib64/python' ] + sys.path import fsimage import grub.GrubConf diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/lowlevel/xc/xc.c Thu Aug 07 11:57:34 2008 +0900 @@ -958,8 +958,7 @@ static PyObject *pyxc_physdev_map_pirq(P if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, &dom, &index, &pirq) ) return NULL; - ret = xc_physdev_map_pirq(xc->xc_handle, dom, MAP_PIRQ_TYPE_GSI, - index, &pirq); + ret = xc_physdev_map_pirq(xc->xc_handle, dom, index, &pirq); if ( ret != 0 ) return pyxc_error_to_exception(); return PyLong_FromUnsignedLong(pirq); diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/util/pci.py --- a/tools/python/xen/util/pci.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/util/pci.py Thu Aug 07 11:57:34 2008 +0900 @@ -44,6 +44,12 @@ PCI_CLASS_DEVICE = 0x0a PCI_CLASS_DEVICE = 0x0a PCI_CLASS_BRIDGE_PCI = 0x0604 +PCI_HEADER_TYPE = 0x0e +PCI_HEADER_TYPE_MASK = 0x7f +PCI_HEADER_TYPE_NORMAL = 0 +PCI_HEADER_TYPE_BRIDGE = 1 +PCI_HEADER_TYPE_CARDBUS = 2 + PCI_CAPABILITY_LIST = 0x34 PCI_CB_BRIDGE_CONTROL = 0x3e PCI_BRIDGE_CTL_BUS_RESET= 0x40 @@ -56,6 +62,12 @@ PCI_EXP_DEVCAP_FLR = (0x1 << 28) PCI_EXP_DEVCAP_FLR = (0x1 << 28) PCI_EXP_DEVCTL = 0x8 PCI_EXP_DEVCTL_FLR = (0x1 << 15) + +PCI_CAP_ID_PM = 0x01 +PCI_PM_CTRL = 4 +PCI_PM_CTRL_NO_SOFT_RESET = 0x0004 +PCI_PM_CTRL_STATE_MASK = 0x0003 +PCI_D3hot = 3 PCI_CAP_ID_AF = 0x13 PCI_AF_CAPs = 0x3 @@ -105,15 +117,22 @@ def parse_hex(val): return None def parse_pci_name(pci_name_string): - # Format: xxxx:xx:xx:x - s = pci_name_string - s = s.split(':') - dom = parse_hex(s[0]) - bus = parse_hex(s[1]) - s = s[2].split('.') - dev = parse_hex(s[0]) - func = parse_hex(s[1]) - return (dom, bus, dev, func) + pci_match = re.match(r"((?P<domain>[0-9a-fA-F]{1,4})[:,])?" + \ + r"(?P<bus>[0-9a-fA-F]{1,2})[:,]" + \ + r"(?P<slot>[0-9a-fA-F]{1,2})[.,]" + \ + r"(?P<func>[0-7])$", pci_name_string) + if pci_match is None: + raise PciDeviceParseError(('Failed to parse pci device name: %s' % + pci_name_string)) + pci_dev_info = pci_match.groupdict('0') + + domain = parse_hex(pci_dev_info['domain']) + bus = parse_hex(pci_dev_info['bus']) + slot = parse_hex(pci_dev_info['slot']) + func = parse_hex(pci_dev_info['func']) + + return (domain, bus, slot, func) + def find_sysfs_mnt(): global sysfs_mnt_point @@ -169,14 +188,14 @@ def create_lspci_info(): # Execute 'lspci' command and parse the result. # If the command does not exist, lspci_info will be kept blank ({}). - for paragraph in os.popen(LSPCI_CMD + ' -vmmD').read().split('\n\n'): + for paragraph in os.popen(LSPCI_CMD + ' -vmm').read().split('\n\n'): device_name = None device_info = {} for line in paragraph.split('\n'): try: (opt, value) = line.split(':\t') if opt == 'Slot': - device_name = value + device_name = PCI_DEV_FORMAT_STR % parse_pci_name(value) else: device_info[opt] = value except: @@ -246,18 +265,8 @@ def transform_list(target, src): return result def check_FLR_capability(dev_list): - i = len(dev_list) - if i == 0: + if len(dev_list) == 0: return [] - i = i - 1; - while i >= 0: - dev = dev_list[i] - if dev.bus == 0: - if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr: - del dev_list[i] - elif dev.dev_type == DEV_TYPE_PCI and not dev.pci_af_flr: - del dev_list[i] - i = i - 1 pci_list = [] pci_dev_dict = {} @@ -270,6 +279,8 @@ def check_FLR_capability(dev_list): for pci in pci_list: if isinstance(pci, types.StringTypes): dev = pci_dev_dict[pci] + if dev.bus == 0: + continue if dev.dev_type == DEV_TYPE_PCIe_ENDPOINT and not dev.pcie_flr: coassigned_pci_list = dev.find_all_the_multi_functions() need_transform = True @@ -336,13 +347,6 @@ class PciDeviceAssignmentError(Exception self.message = msg def __str__(self): return 'pci: impproper device assignment spcified: ' + \ - self.message - -class PciDeviceFlrError(PciDeviceAssignmentError): - def __init__(self,msg): - self.message = msg - def __str__(self): - return 'Can not find a suitable FLR method for the device(s): ' + \ self.message class PciDevice: @@ -480,6 +484,27 @@ class PciDevice: # Restore the config spaces restore_pci_conf_space((pci_list, cfg_list)) + def do_Dstate_transition(self): + pos = self.find_cap_offset(PCI_CAP_ID_PM) + if pos == 0: + return + + (pci_list, cfg_list) = save_pci_conf_space([self.name]) + + # Enter D3hot without soft reset + pm_ctl = self.pci_conf_read32(pos + PCI_PM_CTRL) + pm_ctl |= PCI_PM_CTRL_NO_SOFT_RESET + pm_ctl &= ~PCI_PM_CTRL_STATE_MASK + pm_ctl |= PCI_D3hot + self.pci_conf_write32(pos + PCI_PM_CTRL, pm_ctl) + time.sleep(0.010) + + # From D3hot to D0 + self.pci_conf_write32(pos + PCI_PM_CTRL, 0) + time.sleep(0.010) + + restore_pci_conf_space((pci_list, cfg_list)) + def find_all_the_multi_functions(self): sysfs_mnt = find_sysfs_mnt() pci_names = os.popen('ls ' + sysfs_mnt + SYSFS_PCI_DEVS_PATH).read() @@ -650,13 +675,16 @@ class PciDevice: time.sleep(0.200) restore_pci_conf_space((pci_list, cfg_list)) else: - funcs = self.find_all_the_multi_functions() - self.devs_check_driver(funcs) - - parent = '%04x:%02x:%02x.%01x' % self.find_parent() - - # Do Secondary Bus Reset. - self.do_secondary_bus_reset(parent, funcs) + if self.bus == 0: + self.do_Dstate_transition() + else: + funcs = self.find_all_the_multi_functions() + self.devs_check_driver(funcs) + + parent = '%04x:%02x:%02x.%01x' % self.find_parent() + + # Do Secondary Bus Reset. + self.do_secondary_bus_reset(parent, funcs) # PCI devices else: # For PCI device on host bus, we test "PCI Advanced Capabilities". @@ -669,9 +697,7 @@ class PciDevice: restore_pci_conf_space((pci_list, cfg_list)) else: if self.bus == 0: - err_msg = 'pci: %s is not assignable: it is on bus 0, '+ \ - 'but it has no PCI Advanced Capabilities.' - raise PciDeviceFlrError(err_msg % self.name) + self.do_Dstate_transition() else: devs = self.find_coassigned_devices(False) # Remove the element 0 which is a bridge @@ -690,12 +716,24 @@ class PciDevice: self.name+SYSFS_PCI_DEV_CONFIG_PATH try: conf_file = open(path, 'rb') + conf_file.seek(PCI_HEADER_TYPE) + header_type = ord(conf_file.read(1)) & PCI_HEADER_TYPE_MASK + if header_type == PCI_HEADER_TYPE_CARDBUS: + return conf_file.seek(PCI_STATUS_OFFSET) status = ord(conf_file.read(1)) if status&PCI_STATUS_CAP_MASK: conf_file.seek(PCI_CAP_OFFSET) capa_pointer = ord(conf_file.read(1)) + capa_count = 0 while capa_pointer: + if capa_pointer < 0x40: + raise PciDeviceParseError( + ('Broken capability chain: %s' % self.name)) + capa_count += 1 + if capa_count > 96: + raise PciDeviceParseError( + ('Looped capability chain: %s' % self.name)) conf_file.seek(capa_pointer) capa_id = ord(conf_file.read(1)) capa_pointer = ord(conf_file.read(1)) diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/util/utils.py --- a/tools/python/xen/util/utils.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/util/utils.py Thu Aug 07 11:57:34 2008 +0900 @@ -1,6 +1,50 @@ import traceback import traceback import sys +import os def exception_string(e): (ty,v,tb) = sys.exc_info() return traceback.format_exception_only(ty,v) + +def daemonize(prog, args, stdin_tmpfile=None): + """Runs a program as a daemon with the list of arguments. Returns the PID + of the daemonized program, or returns 0 on error. + """ + r, w = os.pipe() + pid = os.fork() + + if pid == 0: + os.close(r) + w = os.fdopen(w, 'w') + os.setsid() + try: + pid2 = os.fork() + except: + pid2 = None + if pid2 == 0: + os.chdir("/") + null_fd = os.open("/dev/null", os.O_RDWR) + if stdin_tmpfile is not None: + os.dup2(stdin_tmpfile.fileno(), 0) + else: + os.dup2(null_fd, 0) + os.dup2(null_fd, 1) + os.dup2(null_fd, 2) + for fd in range(3, 256): + try: + os.close(fd) + except: + pass + os.execvp(prog, args) + os._exit(1) + else: + w.write(str(pid2 or 0)) + w.close() + os._exit(0) + os.close(w) + r = os.fdopen(r) + daemon_pid = int(r.read()) + r.close() + os.waitpid(pid, 0) + return daemon_pid + diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Aug 07 11:57:34 2008 +0900 @@ -599,14 +599,17 @@ class XendDomainInfo: new_dev['func']) bdf = xc.test_assign_device(self.domid, pci_str) if bdf != 0: + if bdf == -1: + raise VmError("failed to assign device: maybe the platform" + " doesn't support VT-d, or VT-d isn't enabled" + " properly?") bus = (bdf >> 16) & 0xff devfn = (bdf >> 8) & 0xff dev = (devfn >> 3) & 0x1f func = devfn & 0x7 - raise VmError("Fail to hot insert device(%x:%x.%x): maybe VT-d is " - "not enabled, or the device is not exist, or it " - "has already been assigned to other domain" - % (bus, dev, func)) + raise VmError("fail to assign device(%x:%x.%x): maybe it has" + " already been assigned to other domain, or maybe" + " it doesn't exist." % (bus, dev, func)) bdf_str = "%s:%s:%s.%s@%s" % (new_dev['domain'], new_dev['bus'], @@ -635,7 +638,10 @@ class XendDomainInfo: self._waitForDevice(dev_type, devid) except VmError, ex: del self.info['devices'][dev_uuid] - if dev_type == 'tap': + if dev_type == 'pci': + for dev in dev_config_dict['devs']: + XendAPIStore.deregister(dev['uuid'], 'DPCI') + elif dev_type == 'tap': self.info['vbd_refs'].remove(dev_uuid) else: self.info['%s_refs' % dev_type].remove(dev_uuid) @@ -2086,14 +2092,17 @@ class XendDomainInfo: if hvm and pci_str: bdf = xc.test_assign_device(self.domid, pci_str) if bdf != 0: + if bdf == -1: + raise VmError("failed to assign device: maybe the platform" + " doesn't support VT-d, or VT-d isn't enabled" + " properly?") bus = (bdf >> 16) & 0xff devfn = (bdf >> 8) & 0xff dev = (devfn >> 3) & 0x1f func = devfn & 0x7 - raise VmError("Fail to assign device(%x:%x.%x): maybe VT-d is " - "not enabled, or the device is not exist, or it " - "has already been assigned to other domain" - % (bus, dev, func)) + raise VmError("fail to assign device(%x:%x.%x): maybe it has" + " already been assigned to other domain, or maybe" + " it doesn't exist." % (bus, dev, func)) # register the domain in the list from xen.xend import XendDomain @@ -2374,6 +2383,9 @@ class XendDomainInfo: def destroy(self): """Cleanup VM and destroy domain. Nothrow guarantee.""" + if self.domid is None: + return + log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) paths = self._prepare_phantom_paths() diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xend/image.py Thu Aug 07 11:57:34 2008 +0900 @@ -114,7 +114,7 @@ class ImageHandler: self.display = vmConfig['platform'].get('display') self.xauthority = vmConfig['platform'].get('xauthority') - self.vncconsole = vmConfig['platform'].get('vncconsole') + self.vncconsole = int(vmConfig['platform'].get('vncconsole', 0)) self.dmargs = self.parseDeviceModelArgs(vmConfig) self.pid = None rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset') @@ -249,10 +249,6 @@ class ImageHandler: # xm config file def parseDeviceModelArgs(self, vmConfig): ret = ["-domain-name", str(self.vm.info['name_label'])] - - # Tell QEMU how large the guest's memory allocation is - # to help it when loading the initrd (if neccessary) - ret += ["-m", str(self.getRequiredInitialReservation() / 1024)] # Find RFB console device, and if it exists, make QEMU enable # the VNC console. @@ -777,6 +773,10 @@ class HVMImageHandler(ImageHandler): ret.append("tap,vlan=%d,ifname=tap%d.%d,bridge=%s" % (nics, self.vm.getDomid(), nics-1, bridge)) + if nics == 0: + ret.append("-net") + ret.append("none") + return ret def getDeviceModelArgs(self, restore = False): diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xend/server/pciif.py Thu Aug 07 11:57:34 2008 +0900 @@ -375,17 +375,34 @@ class PciController(DevController): raise VmError("pci: failed to locate device and "+ "parse it's resources - "+str(e)) if (dev.dev_type == DEV_TYPE_PCIe_ENDPOINT) and not dev.pcie_flr: - funcs = dev.find_all_the_multi_functions() - for f in funcs: - if not f in pci_str_list: - err_msg = 'pci: % must be co-assigned to guest with %s' - raise VmError(err_msg % (f, dev.name)) + if dev.bus == 0: + # We cope with this case by using the Dstate transition + # method for now. + err_msg = 'pci: %s: it is on bus 0, but has no PCIe' +\ + ' FLR Capability. Will try the Dstate transition'+\ + ' method if available.' + log.warn(err_msg % dev.name) + else: + funcs = dev.find_all_the_multi_functions() + for f in funcs: + if not f in pci_str_list: + (f_dom, f_bus, f_slot, f_func) = parse_pci_name(f) + f_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ + (f_dom, f_bus, f_slot, f_func) + # f has been assigned to other guest? + if xc.test_assign_device(0, f_pci_str) != 0: + err_msg = 'pci: %s must be co-assigned to' + \ + ' the same guest with %s' + raise VmError(err_msg % (f, dev.name)) elif dev.dev_type == DEV_TYPE_PCI: if dev.bus == 0: if not dev.pci_af_flr: - err_msg = 'pci: %s is not assignable: it is on ' + \ - 'bus 0, but lacks of FLR capability' - raise VmError(err_msg % dev.name) + # We cope with this case by using the Dstate transition + # method for now. + err_msg = 'pci: %s: it is on bus 0, but has no PCI' +\ + ' Advanced Capabilities for FLR. Will try the'+\ + ' Dstate transition method if available.' + log.warn(err_msg % dev.name) else: # All devices behind the uppermost PCI/PCI-X bridge must be\ # co-assigned to the same guest. @@ -395,8 +412,14 @@ class PciController(DevController): for s in devs_str: if not s in pci_str_list: - err_msg = 'pci: %s must be co-assigned to guest with %s' - raise VmError(err_msg % (s, dev.name)) + (s_dom, s_bus, s_slot, s_func) = parse_pci_name(s) + s_pci_str = '0x%x,0x%x,0x%x,0x%x' % \ + (s_dom, s_bus, s_slot, s_func) + # s has been assigned to other guest? + if xc.test_assign_device(0, s_pci_str) != 0: + err_msg = 'pci: %s must be co-assigned to the'+\ + ' same guest with %s' + raise VmError(err_msg % (s, dev.name)) for (domain, bus, slot, func) in pci_dev_list: self.setupOneDevice(domain, bus, slot, func) diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xm/console.py --- a/tools/python/xen/xm/console.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xm/console.py Thu Aug 07 11:57:34 2008 +0900 @@ -15,10 +15,69 @@ # Copyright (C) 2005 XenSource Ltd #============================================================================ +import xen.util.auxbin +import xen.lowlevel.xs +import os +import sys +import signal +from xen.util import utils XENCONSOLE = "xenconsole" -import xen.util.auxbin - def execConsole(domid): xen.util.auxbin.execute(XENCONSOLE, [str(domid)]) + + +class OurXenstoreConnection: + def __init__(self): + self.handle = xen.lowlevel.xs.xs() + def read_eventually(self, path): + watch = None + trans = None + try: + signal.alarm(10) + watch = self.handle.watch(path, None) + while True: + result = self.handle.read('0', path) + if result is not None: + signal.alarm(0) + return result + self.handle.read_watch() + finally: + signal.alarm(0) + if watch is not None: self.handle.unwatch(path, watch) + def read_maybe(self, path): + return self.handle.read('0', path) + +def runVncViewer(domid, do_autopass, do_daemonize=False): + xs = OurXenstoreConnection() + d = '/local/domain/%d/' % domid + vnc_port = xs.read_eventually(d + 'console/vnc-port') + vfb_backend = xs.read_maybe(d + 'device/vfb/0/backend') + vnc_listen = None + vnc_password = None + vnc_password_tmpfile = None + cmdl = ['vncviewer'] + if vfb_backend is not None: + vnc_listen = xs.read_maybe(vfb_backend + '/vnclisten') + if do_autopass: + vnc_password = xs.read_maybe(vfb_backend + '/vncpasswd') + if vnc_password is not None: + cmdl.append('-autopass') + vnc_password_tmpfile = os.tmpfile() + print >>vnc_password_tmpfile, vnc_password + vnc_password_tmpfile.seek(0) + vnc_password_tmpfile.flush() + if vnc_listen is None: + vnc_listen = 'localhost' + cmdl.append('%s:%d' % (vnc_listen, int(vnc_port) - 5900)) + if do_daemonize: + pid = utils.daemonize('vncviewer', cmdl, vnc_password_tmpfile) + if pid == 0: + puts >>sys.stderr, 'failed to invoke vncviewer' + os._exit(-1) + else: + print 'invoking ', ' '.join(cmdl) + if vnc_password_tmpfile is not None: + os.dup2(vnc_password_tmpfile.fileno(), 0) + os.execvp('vncviewer', cmdl) diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xm/create.dtd --- a/tools/python/xen/xm/create.dtd Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xm/create.dtd Thu Aug 07 11:57:34 2008 +0900 @@ -39,6 +39,7 @@ vbd*, vif*, vtpm*, + pci*, console*, platform*, vcpu_param*, @@ -79,6 +80,13 @@ <!ELEMENT vtpm (name*)> <!ATTLIST vtpm backend CDATA #REQUIRED> + +<!ELEMENT pci EMPTY> +<!ATTLIST pci domain CDATA #REQUIRED + bus CDATA #REQUIRED + slot CDATA #REQUIRED + func CDATA #REQUIRED + vslt CDATA #IMPLIED> <!ELEMENT console (other_config*)> <!ATTLIST console protocol (vt100|rfb|rdp) #REQUIRED> diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xm/create.py Thu Aug 07 11:57:34 2008 +0900 @@ -36,10 +36,12 @@ from xen.util import vscsi_util from xen.util import vscsi_util import xen.util.xsm.xsm as security from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm +from xen.util import utils from xen.xm.opts import * from main import server +from main import domain_name_to_domid import console @@ -118,6 +120,14 @@ gopts.opt('console_autoconnect', short=' fn=set_true, default=0, use="Connect to the console after the domain is created.") +gopts.opt('vncviewer', + fn=set_true, default=0, + use="Connect to the VNC display after the domain is created.") + +gopts.opt('vncviewer-autopass', + fn=set_true, default=0, + use="Pass VNC password to viewer via stdin and -autopass.") + gopts.var('vncpasswd', val='NAME', fn=set_value, default=None, use="Password for VNC console on HVM domain.") @@ -128,7 +138,7 @@ gopts.var('vncviewer', val='no|yes', "The address of the vncviewer is passed to the domain on the " "kernel command line using 'VNC_SERVER=<host>:<port>'. The port " "used by vnc is 5500 + DISPLAY. A display value with a free port " - "is chosen if possible.\nOnly valid when vnc=1.") + "is chosen if possible.\nOnly valid when vnc=1.\nDEPRECATED") gopts.var('vncconsole', val='no|yes', fn=set_bool, default=None, @@ -1108,44 +1118,6 @@ def choose_vnc_display(): return None vncpid = None -def daemonize(prog, args): - """Runs a program as a daemon with the list of arguments. Returns the PID - of the daemonized program, or returns 0 on error. - """ - r, w = os.pipe() - pid = os.fork() - - if pid == 0: - os.close(r) - w = os.fdopen(w, 'w') - os.setsid() - try: - pid2 = os.fork() - except: - pid2 = None - if pid2 == 0: - os.chdir("/") - for fd in range(0, 256): - try: - os.close(fd) - except: - pass - os.open("/dev/null", os.O_RDWR) - os.dup2(0, 1) - os.dup2(0, 2) - os.execvp(prog, args) - os._exit(1) - else: - w.write(str(pid2 or 0)) - w.close() - os._exit(0) - os.close(w) - r = os.fdopen(r) - daemon_pid = int(r.read()) - r.close() - os.waitpid(pid, 0) - return daemon_pid - def spawn_vnc(display): """Spawns a vncviewer that listens on the specified display. On success, returns the port that the vncviewer is listening on and sets the global @@ -1154,7 +1126,7 @@ def spawn_vnc(display): vncargs = (["vncviewer", "-log", "*:stdout:0", "-listen", "%d" % (VNC_BASE_PORT + display) ]) global vncpid - vncpid = daemonize("vncviewer", vncargs) + vncpid = utils.daemonize("vncviewer", vncargs) if vncpid == 0: return 0 @@ -1362,6 +1334,11 @@ def main(argv): elif not opts.is_xml: dom = make_domain(opts, config) + if opts.vals.vncviewer: + domid = domain_name_to_domid(sxp.child_value(config, 'name', -1)) + vncviewer_autopass = getattr(opts.vals,'vncviewer-autopass', False) + console.runVncViewer(domid, vncviewer_autopass, True) + def do_console(domain_name): cpid = os.fork() if cpid != 0: @@ -1373,13 +1350,7 @@ def do_console(domain_name): if os.WEXITSTATUS(rv) != 0: sys.exit(os.WEXITSTATUS(rv)) try: - # Acquire the console of the created dom - if serverType == SERVER_XEN_API: - domid = server.xenapi.VM.get_domid( - get_single_vm(domain_name)) - else: - dom = server.xend.domain(domain_name) - domid = int(sxp.child_value(dom, 'domid', '-1')) + domid = domain_name_to_domid(domain_name) console.execConsole(domid) except: pass diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xm/main.py Thu Aug 07 11:57:34 2008 +0900 @@ -64,6 +64,9 @@ from xen.xend import XendOptions from xen.xend import XendOptions xoptions = XendOptions.instance() +import signal +signal.signal(signal.SIGINT, signal.SIG_DFL) + # getopt.gnu_getopt is better, but only exists in Python 2.3+. Use # getopt.getopt if gnu_getopt is not available. This will mean that options # may only be specified before positional arguments. @@ -97,6 +100,8 @@ SUBCOMMAND_HELP = { 'console' : ('[-q|--quiet] <Domain>', 'Attach to <Domain>\'s console.'), + 'vncviewer' : ('[--[vncviewer-]autopass] <Domain>', + 'Attach to <Domain>\'s VNC server.'), 'create' : ('<ConfigFile> [options] [vars]', 'Create a domain based on <ConfigFile>.'), 'destroy' : ('<Domain>', @@ -243,6 +248,10 @@ SUBCOMMAND_OPTIONS = { 'console': ( ('-q', '--quiet', 'Do not print an error message if the domain does not exist'), ), + 'vncviewer': ( + ('', '--autopass', 'Pass VNC password to viewer via stdin and -autopass'), + ('', '--vncviewer-autopass', '(consistency alias for --autopass)'), + ), 'dmesg': ( ('-c', '--clear', 'Clear dmesg buffer as well as printing it'), ), @@ -260,6 +269,8 @@ SUBCOMMAND_OPTIONS = { 'start': ( ('-p', '--paused', 'Do not unpause domain after starting it'), ('-c', '--console_autoconnect', 'Connect to the console after the domain is created'), + ('', '--vncviewer', 'Connect to display via VNC after the domain is created'), + ('', '--vncviewer-autopass', 'Pass VNC password to viewer via stdin and -autopass'), ), 'resume': ( ('-p', '--paused', 'Do not unpause domain after resuming it'), @@ -277,6 +288,7 @@ SUBCOMMAND_OPTIONS = { common_commands = [ "console", + "vncviewer", "create", "new", "delete", @@ -304,6 +316,7 @@ common_commands = [ domain_commands = [ "console", + "vncviewer", "create", "new", "delete", @@ -1185,14 +1198,20 @@ def xm_start(args): paused = False console_autoconnect = False + vncviewer = False + vncviewer_autopass = False try: - (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused']) + (options, params) = getopt.gnu_getopt(args, 'cp', ['console_autoconnect','paused','vncviewer','vncviewer-autopass']) for (k, v) in options: if k in ('-p', '--paused'): paused = True if k in ('-c', '--console_autoconnect'): console_autoconnect = True + if k in ('--vncviewer'): + vncviewer = True + if k in ('--vncviewer-autopass'): + vncviewer_autopass = True if len(params) != 1: raise OptionError("Expects 1 argument") @@ -1204,6 +1223,9 @@ def xm_start(args): if console_autoconnect: start_do_console(dom) + + if console_autoconnect: + console.runVncViewer(domid, vncviewer_autopass, True) try: if serverType == SERVER_XEN_API: @@ -1783,6 +1805,40 @@ def xm_console(args): console.execConsole(domid) +def domain_name_to_domid(domain_name): + if serverType == SERVER_XEN_API: + domid = server.xenapi.VM.get_domid( + get_single_vm(domain_name)) + else: + dom = server.xend.domain(domain_name) + domid = int(sxp.child_value(dom, 'domid', '-1')) + return domid + +def xm_vncviewer(args): + autopass = False; + + try: + (options, params) = getopt.gnu_getopt(args, '', ['autopass','vncviewer-autopass']) + except getopt.GetoptError, opterr: + err(opterr) + usage('vncviewer') + + for (k, v) in options: + if k in ['--autopass','--vncviewer-autopass']: + autopass = True + else: + assert False + + if len(params) != 1: + err('No domain given (or several parameters specified)') + usage('vncviewer') + + dom = params[0] + domid = domain_name_to_domid(dom) + + console.runVncViewer(domid, autopass) + + def xm_uptime(args): short_mode = 0 @@ -2102,7 +2158,23 @@ def xm_pci_list(args): dom = params[0] - devs = server.xend.domain.getDeviceSxprs(dom, 'pci') + devs = [] + if serverType == SERVER_XEN_API: + for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)): + ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref) + ppci_record = server.xenapi.PPCI.get_record(ppci_ref) + dev = { + "domain": "0x%04x" % int(ppci_record["domain"]), + "bus": "0x%02x" % int(ppci_record["bus"]), + "slot": "0x%02x" % int(ppci_record["slot"]), + "func": "0x%01x" % int(ppci_record["func"]), + "vslt": "0x%02x" % \ + int(server.xenapi.DPCI.get_hotplug_slot(dpci_ref)) + } + devs.append(dev) + + else: + devs = server.xend.domain.getDeviceSxprs(dom, 'pci') if len(devs) == 0: return @@ -2362,7 +2434,34 @@ def xm_pci_attach(args): def xm_pci_attach(args): arg_check(args, 'pci-attach', 2, 3) (dom, pci) = parse_pci_configuration(args, 'Initialising') - server.xend.domain.device_configure(dom, pci) + + if serverType == SERVER_XEN_API: + + pci_dev = sxp.children(pci, 'dev')[0] + domain = int(sxp.child_value(pci_dev, 'domain'), 16) + bus = int(sxp.child_value(pci_dev, 'bus'), 16) + slot = int(sxp.child_value(pci_dev, 'slot'), 16) + func = int(sxp.child_value(pci_dev, 'func'), 16) + vslt = int(sxp.child_value(pci_dev, 'vslt'), 16) + name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func) + + target_ref = None + for ppci_ref in server.xenapi.PPCI.get_all(): + if name == server.xenapi.PPCI.get_name(ppci_ref): + target_ref = ppci_ref + break + if target_ref is None: + raise OptionError("Device %s not found" % name) + + dpci_record = { + "VM": get_single_vm(dom), + "PPCI": target_ref, + "hotplug_slot": vslt + } + server.xenapi.DPCI.create(dpci_record) + + else: + server.xend.domain.device_configure(dom, pci) def xm_scsi_attach(args): xenapi_unsupported() @@ -2462,7 +2561,29 @@ def xm_pci_detach(args): def xm_pci_detach(args): arg_check(args, 'pci-detach', 2) (dom, pci) = parse_pci_configuration(args, 'Closing') - server.xend.domain.device_configure(dom, pci) + + if serverType == SERVER_XEN_API: + + pci_dev = sxp.children(pci, 'dev')[0] + domain = int(sxp.child_value(pci_dev, 'domain'), 16) + bus = int(sxp.child_value(pci_dev, 'bus'), 16) + slot = int(sxp.child_value(pci_dev, 'slot'), 16) + func = int(sxp.child_value(pci_dev, 'func'), 16) + vslt = int(sxp.child_value(pci_dev, 'vslt'), 16) + name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func) + + target_ref = None + for dpci_ref in server.xenapi.VM.get_DPCIs(get_single_vm(dom)): + ppci_ref = server.xenapi.DPCI.get_PPCI(dpci_ref) + if name == server.xenapi.PPCI.get_name(ppci_ref): + target_ref = ppci_ref + server.xenapi.DPCI.destroy(dpci_ref) + break + if target_ref is None: + raise OptionError("Device %s not assigned" % name) + + else: + server.xend.domain.device_configure(dom, pci) def xm_scsi_detach(args): xenapi_unsupported() @@ -2617,6 +2738,7 @@ commands = { "event-monitor": xm_event_monitor, # console commands "console": xm_console, + "vncviewer": xm_vncviewer, # xenstat commands "top": xm_top, # domain commands diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xm/shutdown.py --- a/tools/python/xen/xm/shutdown.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xm/shutdown.py Thu Aug 07 11:57:34 2008 +0900 @@ -144,9 +144,10 @@ def main_dom(opts, args): def main_dom(opts, args): if len(args) == 0: opts.err('No domain parameter given') if len(args) > 1: opts.err('No multiple domain parameters allowed') - dom = sxp.child_value(server.xend.domain(args[0]), 'name') if serverType == SERVER_XEN_API: - dom = get_single_vm(dom) + dom = get_single_vm(args[0]) + else: + dom = sxp.child_value(server.xend.domain(args[0]), 'name') mode = shutdown_mode(opts) shutdown(opts, [ dom ], mode, opts.vals.wait) diff -r 7affdebb7a1e -r a39913db6e51 tools/python/xen/xm/xenapi_create.py --- a/tools/python/xen/xm/xenapi_create.py Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/python/xen/xm/xenapi_create.py Thu Aug 07 11:57:34 2008 +0900 @@ -369,6 +369,12 @@ class xenapi_create: self.create_consoles(vm_ref, consoles) + # Now create pcis + + pcis = vm.getElementsByTagName("pci") + + self.create_pcis(vm_ref, pcis) + return vm_ref except: server.xenapi.VM.destroy(vm_ref) @@ -389,7 +395,7 @@ class xenapi_create: "device": vbd.attributes["device"].value, "bootable": - vbd.attributes["bootable"].value == "True", + vbd.attributes["bootable"].value == "1", "mode": vbd.attributes["mode"].value, "type": @@ -493,6 +499,39 @@ class xenapi_create: return server.xenapi.console.create(console_record) + def create_pcis(self, vm_ref, pcis): + log(DEBUG, "create_pcis") + return map(lambda pci: self.create_pci(vm_ref, pci), pcis) + + def create_pci(self, vm_ref, pci): + log(DEBUG, "create_pci") + + domain = int(pci.attributes["domain"].value, 16) + bus = int(pci.attributes["bus"].value, 16) + slot = int(pci.attributes["slot"].value, 16) + func = int(pci.attributes["func"].value, 16) + name = "%04x:%02x:%02x.%01x" % (domain, bus, slot, func) + + target_ref = None + for ppci_ref in server.xenapi.PPCI.get_all(): + if name == server.xenapi.PPCI.get_name(ppci_ref): + target_ref = ppci_ref + break + if target_ref is None: + log(DEBUG, "create_pci: pci device not found") + return None + + dpci_record = { + "VM": + vm_ref, + "PPCI": + target_ref, + "hotplug_slot": + int(pci.attributes["func"].value, 16) + } + + return server.xenapi.DPCI.create(dpci_record) + def get_child_by_name(exp, childname, default = None): try: return [child for child in sxp.children(exp) @@ -520,6 +559,9 @@ class sxp2xml: vfbs_sxp = map(lambda x: x[1], [device for device in devices if device[1][0] == "vfb"]) + + pcis_sxp = map(lambda x: x[1], [device for device in devices + if device[1][0] == "pci"]) # Create XML Document @@ -597,13 +639,15 @@ class sxp2xml: pv = document.createElement("pv") pv.attributes["kernel"] \ = get_child_by_name(image, "kernel", "") - pv.attributes["bootloader"] = "" + pv.attributes["bootloader"] \ + = get_child_by_name(config, "bootloader", "") pv.attributes["ramdisk"] \ = get_child_by_name(image, "ramdisk", "") pv.attributes["args"] \ = "root=" + get_child_by_name(image, "root", "") \ + " " + get_child_by_name(image, "args", "") - pv.attributes["bootloader_args"] = "" + pv.attributes["bootloader_args"] \ + = get_child_by_name(config, "bootloader_args","") vm.appendChild(pv) elif image[0] == "hvm": @@ -653,6 +697,12 @@ class sxp2xml: vtpms = map(lambda vtpm: self.extract_vtpm(vtpm, document), vtpms_sxp) map(vm.appendChild, vtpms) + + # And now the pcis + + pcis = self.extract_pcis(pcis_sxp, document) + + map(vm.appendChild, pcis) # Last but not least the consoles... @@ -821,7 +871,28 @@ class sxp2xml: return vfb - _eths = -1 + def extract_pcis(self, pcis_sxp, document): + + pcis = [] + + for pci_sxp in pcis_sxp: + for dev_sxp in sxp.children(pci_sxp, "dev"): + pci = document.createElement("pci") + + pci.attributes["domain"] \ + = get_child_by_name(dev_sxp, "domain", "0") + pci.attributes["bus"] \ + = get_child_by_name(dev_sxp, "bus", "0") + pci.attributes["slot"] \ + = get_child_by_name(dev_sxp, "slot", "0") + pci.attributes["func"] \ + = get_child_by_name(dev_sxp, "func", "0") + pci.attributes["vslt"] \ + = get_child_by_name(dev_sxp, "vslt", "0") + + pcis.append(pci) + + return pcis def mk_other_config(self, key, value, document): other_config = document.createElement("other_config") @@ -914,6 +985,8 @@ class sxp2xml: return platform_configs + _eths = -1 + def getFreshEthDevice(self): self._eths += 1 return "eth%i" % self._eths diff -r 7affdebb7a1e -r a39913db6e51 tools/xenmon/Makefile --- a/tools/xenmon/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/xenmon/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -33,6 +33,8 @@ install: build $(INSTALL_PROG) xenbaked $(DESTDIR)$(SBINDIR)/xenbaked $(INSTALL_PROG) xentrace_setmask $(DESTDIR)$(SBINDIR)/xentrace_setmask $(INSTALL_PROG) xenmon.py $(DESTDIR)$(SBINDIR)/xenmon.py + $(INSTALL_DIR) $(DESTDIR)$(DOCDIR) + $(INSTALL_DATA) README $(DESTDIR)$(DOCDIR)/README.xenmon .PHONY: clean clean: diff -r 7affdebb7a1e -r a39913db6e51 tools/xenstat/libxenstat/Makefile --- a/tools/xenstat/libxenstat/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/xenstat/libxenstat/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -15,7 +15,7 @@ XEN_ROOT=../../.. XEN_ROOT=../../.. include $(XEN_ROOT)/tools/Rules.mk -prefix=/usr +prefix=$(PREFIX) includedir=$(prefix)/include libdir=$(prefix)/lib diff -r 7affdebb7a1e -r a39913db6e51 tools/xenstat/libxenstat/src/xenstat.c --- a/tools/xenstat/libxenstat/src/xenstat.c Thu Aug 07 11:47:34 2008 +0900 +++ b/tools/xenstat/libxenstat/src/xenstat.c Thu Aug 07 11:57:34 2008 +0900 @@ -109,7 +109,7 @@ xenstat_handle *xenstat_init(void) handle->xshandle = xs_daemon_open_readonly(); /* open handle to xenstore*/ if (handle->xshandle == NULL) { - perror("unable to open xenstore\n"); + perror("unable to open xenstore"); xc_interface_close(handle->xc_handle); free(handle); return NULL; diff -r 7affdebb7a1e -r a39913db6e51 unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c --- a/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Thu Aug 07 11:47:34 2008 +0900 +++ b/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Thu Aug 07 11:57:34 2008 +0900 @@ -71,7 +71,7 @@ static int bp_suspend(void) return suspend_cancelled; } -int __xen_suspend(int fast_suspend, void (*resume_notifier)(void)) +int __xen_suspend(int fast_suspend, void (*resume_notifier)(int)) { int err, suspend_cancelled, nr_cpus; struct ap_suspend_info info; @@ -101,7 +101,7 @@ int __xen_suspend(int fast_suspend, void local_irq_disable(); suspend_cancelled = bp_suspend(); - resume_notifier(); + resume_notifier(suspend_cancelled); local_irq_enable(); smp_mb(); diff -r 7affdebb7a1e -r a39913db6e51 xen/Makefile --- a/xen/Makefile Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/Makefile Thu Aug 07 11:57:34 2008 +0900 @@ -1,8 +1,8 @@ # This is the correct place to edit the build version. # All other places this is stored (eg. compile.h) should be autogenerated. -export XEN_VERSION = 3 -export XEN_SUBVERSION = 3 -export XEN_EXTRAVERSION ?= -unstable$(XEN_VENDORVERSION) +export XEN_VERSION = 4 +export XEN_SUBVERSION = 0 +export XEN_EXTRAVERSION ?= .0-rc3-pre$(XEN_VENDORVERSION) export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION) -include xen-version diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/ia64/xen/domain.c Thu Aug 07 11:57:34 2008 +0900 @@ -2212,8 +2212,9 @@ int __init construct_dom0(struct domain return 0; } -void machine_restart(void) -{ +void machine_restart(unsigned int delay_millisecs) +{ + mdelay(delay_millisecs); console_start_sync(); if (running_on_sim) printk ("machine_restart called. spinning...\n"); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/ia64/xen/irq.c --- a/xen/arch/ia64/xen/irq.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/ia64/xen/irq.c Thu Aug 07 11:57:34 2008 +0900 @@ -459,7 +459,7 @@ int pirq_guest_bind(struct vcpu *v, int return rc; } -int pirq_guest_unbind(struct domain *d, int irq) +void pirq_guest_unbind(struct domain *d, int irq) { irq_desc_t *desc = &irq_desc[irq]; irq_guest_action_t *action; @@ -493,7 +493,6 @@ int pirq_guest_unbind(struct domain *d, } spin_unlock_irqrestore(&desc->lock, flags); - return 0; } void diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/acpi/cpufreq/utility.c --- a/xen/arch/x86/acpi/cpufreq/utility.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/acpi/cpufreq/utility.c Thu Aug 07 11:57:34 2008 +0900 @@ -296,12 +296,11 @@ void cpufreq_suspend(void) { int cpu; - /* to protect the case when Px was controlled by dom0-kernel */ - /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */ + /* to protect the case when Px was not controlled by xen */ for_each_online_cpu(cpu) { struct processor_performance *perf = &processor_pminfo[cpu].perf; - if (!perf->init) + if (!(perf->init & XEN_PX_INIT)) return; } @@ -316,14 +315,13 @@ int cpufreq_resume(void) { int cpu, ret = 0; - /* 1. to protect the case when Px was controlled by dom0-kernel */ - /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */ + /* 1. to protect the case when Px was not controlled by xen */ /* 2. set state and resume flag to sync cpu to right state and freq */ for_each_online_cpu(cpu) { struct processor_performance *perf = &processor_pminfo[cpu].perf; struct cpufreq_policy *policy = &xen_px_policy[cpu]; - if (!perf->init) + if (!(perf->init & XEN_PX_INIT)) goto err; perf->state = 0; policy->resume = 1; diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/acpi/pmstat.c --- a/xen/arch/x86/acpi/pmstat.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/acpi/pmstat.c Thu Aug 07 11:57:34 2008 +0900 @@ -52,9 +52,9 @@ int do_get_pm_info(struct xen_sysctl_get struct pm_px *pxpt = &px_statistic_data[op->cpuid]; struct processor_pminfo *pmpt = &processor_pminfo[op->cpuid]; - /* to protect the case when Px was controlled by dom0-kernel */ - /* or when CPU_FREQ not set in which case ACPI Px objects not parsed */ - if ( !pmpt->perf.init && (op->type & PMSTAT_CATEGORY_MASK) == PMSTAT_PX ) + /* to protect the case when Px was not controlled by xen */ + if ( (!(pmpt->perf.init & XEN_PX_INIT)) && + (op->type & PMSTAT_CATEGORY_MASK) == PMSTAT_PX ) return -EINVAL; if ( !cpu_online(op->cpuid) ) diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/domain.c Thu Aug 07 11:57:34 2008 +0900 @@ -1811,7 +1811,6 @@ int domain_relinquish_resources(struct d if ( ret ) return ret; #endif - WARN_ON(d->xenheap_pages); break; default: diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/domain_build.c Thu Aug 07 11:57:34 2008 +0900 @@ -757,6 +757,7 @@ int __init construct_dom0( si->shared_info = virt_to_maddr(d->shared_info); si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; + si->flags |= (xen_processor_pmbits << 8) & SIF_PM_MASK; si->pt_base = vpt_start + 2 * PAGE_SIZE * !!is_pv_32on64_domain(d); si->nr_pt_frames = nr_pt_pages; si->mfn_list = vphysmap_start; diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/domctl.c Thu Aug 07 11:57:34 2008 +0900 @@ -661,6 +661,7 @@ long arch_do_domctl( if ( !iommu_pv_enabled && !is_hvm_domain(d) ) { ret = -ENOSYS; + put_domain(d); break; } @@ -669,12 +670,16 @@ long arch_do_domctl( gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: " "%x:%x:%x already assigned, or non-existent\n", bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + put_domain(d); break; } ret = assign_device(d, bus, devfn); - gdprintk(XENLOG_INFO, "XEN_DOMCTL_assign_device: bdf = %x:%x:%x\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + if ( ret ) + gdprintk(XENLOG_ERR, "XEN_DOMCTL_assign_device: " + "assign device (%x:%x:%x) failed\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); + put_domain(d); } break; @@ -701,11 +706,15 @@ long arch_do_domctl( if ( !iommu_pv_enabled && !is_hvm_domain(d) ) { ret = -ENOSYS; + put_domain(d); break; } if ( !device_assigned(bus, devfn) ) - break; + { + put_domain(d); + break; + } ret = 0; deassign_device(d, bus, devfn); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/hvm/io.c Thu Aug 07 11:57:34 2008 +0900 @@ -284,7 +284,7 @@ void dpci_ioport_write(uint32_t mport, i data = p->data; if ( p->data_is_ptr ) (void)hvm_copy_from_guest_phys( - &data, p->data + (sign * i & p->size), p->size); + &data, p->data + (sign * i * p->size), p->size); switch ( p->size ) { diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/hvm/stdvga.c --- a/xen/arch/x86/hvm/stdvga.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/hvm/stdvga.c Thu Aug 07 11:57:34 2008 +0900 @@ -33,6 +33,10 @@ #include <xen/domain_page.h> #include <asm/hvm/support.h> #include <xen/numa.h> +#include <xen/paging.h> + +#define VGA_MEM_BASE 0xa0000 +#define VGA_MEM_SIZE 0x20000 #define PAT(x) (x) static const uint32_t mask16[16] = { @@ -464,6 +468,7 @@ static int mmio_move(struct hvm_hw_stdvg { int i; int sign = p->df ? -1 : 1; + p2m_type_t p2mt; if ( p->data_is_ptr ) { @@ -473,7 +478,19 @@ static int mmio_move(struct hvm_hw_stdvg for ( i = 0; i < p->count; i++ ) { tmp = stdvga_mem_read(addr, p->size); - hvm_copy_to_guest_phys(data, &tmp, p->size); + if ( hvm_copy_to_guest_phys(data, &tmp, p->size) == + HVMCOPY_bad_gfn_to_mfn ) + { + (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt); + /* + * The only case we handle is vga_mem <-> vga_mem. + * Anything else disables caching and leaves it to qemu-dm. + */ + if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) || + ((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) ) + return 0; + stdvga_mem_write(data, tmp, p->size); + } data += sign * p->size; addr += sign * p->size; } @@ -483,7 +500,15 @@ static int mmio_move(struct hvm_hw_stdvg uint32_t addr = p->addr, data = p->data, tmp; for ( i = 0; i < p->count; i++ ) { - hvm_copy_from_guest_phys(&tmp, data, p->size); + if ( hvm_copy_from_guest_phys(&tmp, data, p->size) == + HVMCOPY_bad_gfn_to_mfn ) + { + (void)gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt); + if ( (p2mt != p2m_mmio_dm) || (data < VGA_MEM_BASE) || + ((data + p->size) > (VGA_MEM_BASE + VGA_MEM_SIZE)) ) + return 0; + tmp = stdvga_mem_read(data, p->size); + } stdvga_mem_write(addr, tmp, p->size); data += sign * p->size; addr += sign * p->size; @@ -536,7 +561,8 @@ static int stdvga_intercept_mmio(ioreq_t { case IOREQ_TYPE_COPY: buf = mmio_move(s, p); - break; + if ( buf ) + break; default: gdprintk(XENLOG_WARNING, "unsupported mmio request type:%d " "addr:0x%04x data:0x%04x size:%d count:%d state:%d " @@ -588,7 +614,7 @@ void stdvga_init(struct domain *d) register_portio_handler(d, 0x3ce, 2, stdvga_intercept_pio); /* MMIO. */ register_buffered_io_handler( - d, 0xa0000, 0x20000, stdvga_intercept_mmio); + d, VGA_MEM_BASE, VGA_MEM_SIZE, stdvga_intercept_mmio); } } diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Aug 07 11:57:34 2008 +0900 @@ -874,9 +874,12 @@ static void svm_do_nested_pgfault(paddr_ mfn_t mfn; unsigned long gfn = gpa >> PAGE_SHIFT; - /* If this GFN is emulated MMIO, pass the fault to the mmio handler */ + /* + * If this GFN is emulated MMIO or marked as read-only, pass the fault + * to the mmio handler. + */ mfn = gfn_to_mfn_current(gfn, &p2mt); - if ( p2mt == p2m_mmio_dm ) + if ( (p2mt == p2m_mmio_dm) || (p2mt == p2m_ram_ro) ) { if ( !handle_mmio() ) hvm_inject_exception(TRAP_gp_fault, 0, 0); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Aug 07 11:57:34 2008 +0900 @@ -1971,7 +1971,7 @@ static void ept_handle_violation(unsigne } mfn = gfn_to_mfn(d, gfn, &t); - if ( p2m_is_ram(t) && paging_mode_log_dirty(d) ) + if ( (t != p2m_ram_ro) && p2m_is_ram(t) && paging_mode_log_dirty(d) ) { paging_mark_dirty(d, mfn_x(mfn)); p2m_change_type(d, gfn, p2m_ram_logdirty, p2m_ram_rw); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/io_apic.c --- a/xen/arch/x86/io_apic.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/io_apic.c Thu Aug 07 11:57:34 2008 +0900 @@ -45,12 +45,12 @@ int (*ioapic_renumber_irq)(int ioapic, i int (*ioapic_renumber_irq)(int ioapic, int irq); atomic_t irq_mis_count; -int msi_irq_enable = 0; -boolean_param("msi_irq_enable", msi_irq_enable); +int msi_enable = 0; +boolean_param("msi", msi_enable); int domain_irq_to_vector(struct domain *d, int irq) { - if ( !msi_irq_enable ) + if ( !msi_enable ) return irq_to_vector(irq); else return d->arch.pirq_vector[irq]; @@ -58,7 +58,7 @@ int domain_irq_to_vector(struct domain * int domain_vector_to_irq(struct domain *d, int vector) { - if ( !msi_irq_enable ) + if ( !msi_enable ) return vector_to_irq(vector); else return d->arch.vector_pirq[vector]; diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/irq.c Thu Aug 07 11:57:34 2008 +0900 @@ -573,7 +573,7 @@ int pirq_guest_bind(struct vcpu *v, int return rc; } -int pirq_guest_unbind(struct domain *d, int irq) +void pirq_guest_unbind(struct domain *d, int irq) { unsigned int vector; irq_desc_t *desc; @@ -660,7 +660,6 @@ int pirq_guest_unbind(struct domain *d, out: spin_unlock_irqrestore(&desc->lock, flags); - return 0; } extern void dump_ioapic_irq_info(void); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/mm.c Thu Aug 07 11:57:34 2008 +0900 @@ -1138,8 +1138,10 @@ static int alloc_l2_table(struct page_in for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) { - if ( is_guest_l2_slot(d, type, i) && - unlikely(!get_page_from_l2e(pl2e[i], pfn, d)) ) + if ( !is_guest_l2_slot(d, type, i) ) + continue; + + if ( unlikely(!get_page_from_l2e(pl2e[i], pfn, d)) ) goto fail; adjust_guest_l2e(pl2e[i], d); @@ -1206,8 +1208,9 @@ static int alloc_l3_table(struct page_in d) ) goto fail; } - else if ( is_guest_l3_slot(i) && - unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) ) + else if ( !is_guest_l3_slot(i) ) + continue; + else if ( unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) ) goto fail; adjust_guest_l3e(pl3e[i], d); @@ -1222,8 +1225,12 @@ static int alloc_l3_table(struct page_in fail: MEM_LOG("Failure in alloc_l3_table: entry %d", i); while ( i-- > 0 ) - if ( is_guest_l3_slot(i) ) - put_page_from_l3e(pl3e[i], pfn); + { + if ( !is_guest_l3_slot(i) ) + continue; + unadjust_guest_l3e(pl3e[i], d); + put_page_from_l3e(pl3e[i], pfn); + } unmap_domain_page(pl3e); return 0; @@ -1242,8 +1249,10 @@ static int alloc_l4_table(struct page_in for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) { - if ( is_guest_l4_slot(d, i) && - unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) + if ( !is_guest_l4_slot(d, i) ) + continue; + + if ( unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) goto fail; adjust_guest_l4e(pl4e[i], d); @@ -1585,7 +1594,7 @@ static int mod_l3_entry(l3_pgentry_t *pl struct vcpu *curr = current; struct domain *d = curr->domain; struct page_info *l3pg = mfn_to_page(pfn); - int okay, rc = 1; + int rc = 1; if ( unlikely(!is_guest_l3_slot(pgentry_ptr_to_slot(pl3e))) ) { @@ -1642,10 +1651,13 @@ static int mod_l3_entry(l3_pgentry_t *pl return 0; } - okay = create_pae_xen_mappings(d, pl3e); - BUG_ON(!okay); - - pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e); + if ( likely(rc) ) + { + if ( !create_pae_xen_mappings(d, pl3e) ) + BUG(); + + pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e); + } page_unlock(l3pg); put_page_from_l3e(ol3e, pfn); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/mm/shadow/multi.c --- a/xen/arch/x86/mm/shadow/multi.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/mm/shadow/multi.c Thu Aug 07 11:57:34 2008 +0900 @@ -3359,7 +3359,7 @@ static int sh_page_fault(struct vcpu *v, gdprintk(XENLOG_DEBUG, "guest attempted write to read-only memory" " page. va page=%#lx, mfn=%#lx\n", va & PAGE_MASK, mfn_x(gmfn)); - goto emulate; /* skip over the instruction */ + goto emulate_readonly; /* skip over the instruction */ } /* In HVM guests, we force CR0.WP always to be set, so that the @@ -3404,6 +3404,11 @@ static int sh_page_fault(struct vcpu *v, goto done; } + /* + * Write from userspace to ro-mem needs to jump here to avoid getting + * caught by user-mode page-table check above. + */ + emulate_readonly: /* * We don't need to hold the lock for the whole emulation; we will * take it again when we write to the pagetables. @@ -4640,14 +4645,8 @@ static void *emulate_map_dest(struct vcp u32 bytes, struct sh_emulate_ctxt *sh_ctxt) { - struct segment_register *sreg; unsigned long offset; void *map = NULL; - - /* We don't emulate user-mode writes to page tables */ - sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); - if ( sreg->attr.fields.dpl == 3 ) - return MAPPING_UNHANDLEABLE; sh_ctxt->mfn1 = emulate_gva_to_mfn(v, vaddr, sh_ctxt); if ( !mfn_valid(sh_ctxt->mfn1) ) @@ -4656,6 +4655,16 @@ static void *emulate_map_dest(struct vcp (mfn_x(sh_ctxt->mfn1) == READONLY_GFN) ? MAPPING_SILENT_FAIL : MAPPING_UNHANDLEABLE); +#ifndef NDEBUG + /* We don't emulate user-mode writes to page tables */ + if ( hvm_get_seg_reg(x86_seg_ss, sh_ctxt)->attr.fields.dpl == 3 ) + { + gdprintk(XENLOG_DEBUG, "User-mode write to pagetable reached " + "emulate_map_dest(). This should never happen!\n"); + return MAPPING_UNHANDLEABLE; + } +#endif + /* Unaligned writes mean probably this isn't a pagetable */ if ( vaddr & (bytes - 1) ) sh_remove_shadows(v, sh_ctxt->mfn1, 0, 0 /* Slow, can fail */ ); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/msi.c --- a/xen/arch/x86/msi.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/msi.c Thu Aug 07 11:57:34 2008 +0900 @@ -27,8 +27,6 @@ #include <public/physdev.h> #include <xen/iommu.h> -extern int msi_irq_enable; - /* bitmap indicate which fixed map is free */ DEFINE_SPINLOCK(msix_fixmap_lock); DECLARE_BITMAP(msix_fixmap_pages, MAX_MSIX_PAGES); @@ -763,14 +761,13 @@ retry: { desc = &irq_desc[entry->vector]; - local_irq_save(flags); - if ( !spin_trylock(&desc->lock) ) - { - local_irq_restore(flags); - goto retry; - } - - spin_lock_irqsave(&desc->lock, flags); + local_irq_save(flags); + if ( !spin_trylock(&desc->lock) ) + { + local_irq_restore(flags); + goto retry; + } + if ( desc->handler == &pci_msi_type ) { /* MSI is not shared, so should be released already */ diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/numa.c --- a/xen/arch/x86/numa.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/numa.c Thu Aug 07 11:57:34 2008 +0900 @@ -14,6 +14,7 @@ #include <xen/time.h> #include <xen/smp.h> #include <asm/acpi.h> +#include <xen/sched.h> static int numa_setup(char *s); custom_param("numa", numa_setup); @@ -281,6 +282,9 @@ static void dump_numa(unsigned char key) { s_time_t now = NOW(); int i; + struct domain *d; + struct page_info *page; + unsigned int page_num_node[MAX_NUMNODES]; printk("'%c' pressed -> dumping numa info (now-0x%X:%08X)\n", key, (u32)(now>>32), (u32)now); @@ -297,6 +301,28 @@ static void dump_numa(unsigned char key) } for_each_online_cpu(i) printk("CPU%d -> NODE%d\n", i, cpu_to_node[i]); + + rcu_read_lock(&domlist_read_lock); + + printk("Memory location of each domain:\n"); + for_each_domain(d) + { + printk("Domain %u (total: %u):\n", d->domain_id, d->tot_pages); + + for_each_online_node(i) + page_num_node[i] = 0; + + list_for_each_entry(page, &d->page_list, list) + { + i = phys_to_nid(page_to_mfn(page) << PAGE_SHIFT); + page_num_node[i]++; + } + + for_each_online_node(i) + printk(" Node %u: %u\n", i, page_num_node[i]); + } + + rcu_read_unlock(&domlist_read_lock); } static __init int register_numa_trigger(void) diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/physdev.c Thu Aug 07 11:57:34 2008 +0900 @@ -184,15 +184,14 @@ static int unmap_domain_pirq(struct doma return ret; } -extern int msi_irq_enable; static int physdev_map_pirq(struct physdev_map_pirq *map) { struct domain *d; int vector, pirq, ret = 0; unsigned long flags; - /* if msi_irq_enable is not enabled,map always success */ - if ( !msi_irq_enable ) + /* if msi_enable is not enabled, map always succeeds */ + if ( !msi_enable ) return 0; if ( !IS_PRIV(current->domain) ) @@ -304,7 +303,7 @@ static int physdev_unmap_pirq(struct phy unsigned long flags; int ret; - if ( !msi_irq_enable ) + if ( !msi_enable ) return 0; if ( !IS_PRIV(current->domain) ) @@ -455,7 +454,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H ret = 0; - if ( msi_irq_enable ) + if ( msi_enable ) { spin_lock_irqsave(&dom0->arch.irq_lock, flags); if ( irq != AUTO_ASSIGN ) diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/platform_hypercall.c --- a/xen/arch/x86/platform_hypercall.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/platform_hypercall.c Thu Aug 07 11:57:34 2008 +0900 @@ -355,6 +355,11 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe struct processor_pminfo *pmpt; struct processor_performance *pxpt; + if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) ) + { + ret = -ENOSYS; + break; + } if ( cpuid < 0 ) { ret = -EINVAL; @@ -373,6 +378,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe memcpy ((void *)&pxpt->status_register, (void *)&xenpxpt->status_register, sizeof(struct xen_pct_register)); + pxpt->init |= XEN_PX_PCT; } if ( xenpxpt->flags & XEN_PX_PSS ) { @@ -390,6 +396,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe break; } pxpt->state_count = xenpxpt->state_count; + pxpt->init |= XEN_PX_PSS; } if ( xenpxpt->flags & XEN_PX_PSD ) { @@ -397,14 +404,18 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe memcpy ((void *)&pxpt->domain_info, (void *)&xenpxpt->domain_info, sizeof(struct xen_psd_package)); + pxpt->init |= XEN_PX_PSD; } if ( xenpxpt->flags & XEN_PX_PPC ) + { pxpt->ppc = xenpxpt->ppc; - - if ( xenpxpt->flags == ( XEN_PX_PCT | XEN_PX_PSS | - XEN_PX_PSD | XEN_PX_PPC ) ) - { - pxpt->init =1; + pxpt->init |= XEN_PX_PPC; + } + + if ( pxpt->init == ( XEN_PX_PCT | XEN_PX_PSS | + XEN_PX_PSD | XEN_PX_PPC ) ) + { + pxpt->init |= XEN_PX_INIT; cpu_count++; } if ( cpu_count == num_online_cpus() ) @@ -418,10 +429,20 @@ ret_t do_platform_op(XEN_GUEST_HANDLE(xe } case XEN_PM_CX: + if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_CX) ) + { + ret = -ENOSYS; + break; + } ret = set_cx_pminfo(op->u.set_pminfo.id, &op->u.set_pminfo.power); break; case XEN_PM_TX: + if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_TX) ) + { + ret = -ENOSYS; + break; + } ret = -EINVAL; break; diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/setup.c Thu Aug 07 11:57:34 2008 +0900 @@ -997,7 +997,6 @@ void __init __start_xen(unsigned long mb if ( (cmdline != NULL) || (kextra != NULL) ) { static char dom0_cmdline[MAX_GUEST_CMDLINE]; - char xen_pm_param[32]; cmdline = cmdline_cook(cmdline); safe_strcpy(dom0_cmdline, cmdline); @@ -1022,14 +1021,6 @@ void __init __start_xen(unsigned long mb safe_strcat(dom0_cmdline, " acpi="); safe_strcat(dom0_cmdline, acpi_param); } - if ( xen_cpuidle ) - xen_processor_pmbits |= XEN_PROCESSOR_PM_CX; - - snprintf(xen_pm_param, sizeof(xen_pm_param), - " xen_processor_pmbits=%d", xen_processor_pmbits); - - if ( !strstr(dom0_cmdline, "xen_processor_pmbits=") ) - safe_strcat(dom0_cmdline, xen_pm_param); cmdline = dom0_cmdline; } @@ -1040,6 +1031,9 @@ void __init __start_xen(unsigned long mb (mod[initrdidx].mod_start - mod[0].mod_start); _initrd_len = mod[initrdidx].mod_end - mod[initrdidx].mod_start; } + + if ( xen_cpuidle ) + xen_processor_pmbits |= XEN_PROCESSOR_PM_CX; /* * We're going to setup domain0 using the module(s) that we stashed safely diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/shutdown.c --- a/xen/arch/x86/shutdown.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/shutdown.c Thu Aug 07 11:57:34 2008 +0900 @@ -291,7 +291,12 @@ __initcall(reboot_init); #endif -void machine_restart(void) +static void __machine_restart(void *pdelay) +{ + machine_restart(*(unsigned int *)pdelay); +} + +void machine_restart(unsigned int delay_millisecs) { int i; @@ -304,13 +309,15 @@ void machine_restart(void) if ( get_apic_id() != boot_cpu_physical_apicid ) { /* Send IPI to the boot CPU (logical cpu 0). */ - on_selected_cpus(cpumask_of_cpu(0), (void *)machine_restart, - NULL, 1, 0); + on_selected_cpus(cpumask_of_cpu(0), __machine_restart, + &delay_millisecs, 1, 0); for ( ; ; ) halt(); } smp_send_stop(); + + mdelay(delay_millisecs); if ( tboot_in_measured_env() ) tboot_shutdown(TB_SHUTDOWN_REBOOT); diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/time.c Thu Aug 07 11:57:34 2008 +0900 @@ -35,8 +35,6 @@ static char opt_clocksource[10]; static char opt_clocksource[10]; string_param("clocksource", opt_clocksource); -#define EPOCH MILLISECS(1000) - unsigned long cpu_khz; /* CPU clock frequency in kHz. */ DEFINE_SPINLOCK(rtc_lock); unsigned long pit0_ticks; @@ -55,7 +53,6 @@ struct cpu_time { s_time_t stime_master_stamp; struct time_scale tsc_scale; u64 cstate_plt_count_stamp; - struct timer calibration_timer; }; struct platform_timesource { @@ -66,6 +63,10 @@ struct platform_timesource { }; static DEFINE_PER_CPU(struct cpu_time, cpu_time); + +/* Calibrate all CPUs to platform timer every EPOCH. */ +#define EPOCH MILLISECS(1000) +static struct timer calibration_timer; /* TSC is invariant on C state entry? */ static bool_t tsc_invariant; @@ -481,35 +482,6 @@ static int init_pmtimer(struct platform_ } /************************************************************ - * PLATFORM TIMER 5: TSC - */ - -static const char plt_tsc_name[] = "TSC"; -#define platform_timer_is_tsc() (plt_src.name == plt_tsc_name) - -static int init_tsctimer(struct platform_timesource *pts) -{ - if ( !tsc_invariant ) - return 0; - - pts->name = (char *)plt_tsc_name; - return 1; -} - -static void make_tsctimer_record(void) -{ - struct cpu_time *t = &this_cpu(cpu_time); - s_time_t now; - u64 tsc; - - rdtscll(tsc); - now = scale_delta(tsc, &t->tsc_scale); - - t->local_tsc_stamp = tsc; - t->stime_local_stamp = t->stime_master_stamp = now; -} - -/************************************************************ * GENERIC PLATFORM TIMER INFRASTRUCTURE */ @@ -530,11 +502,11 @@ static void plt_overflow(void *unused) { u64 count; - spin_lock(&platform_timer_lock); + spin_lock_irq(&platform_timer_lock); count = plt_src.read_counter(); plt_stamp64 += (count - plt_stamp) & plt_mask; plt_stamp = count; - spin_unlock(&platform_timer_lock); + spin_unlock_irq(&platform_timer_lock); set_timer(&plt_overflow_timer, NOW() + plt_overflow_period); } @@ -550,6 +522,8 @@ static s_time_t read_platform_stime(void { u64 count; s_time_t stime; + + ASSERT(!local_irq_is_enabled()); spin_lock(&platform_timer_lock); count = plt_stamp64 + ((plt_src.read_counter() - plt_stamp) & plt_mask); @@ -564,22 +538,16 @@ static void platform_time_calibration(vo u64 count; s_time_t stamp; - spin_lock(&platform_timer_lock); + spin_lock_irq(&platform_timer_lock); count = plt_stamp64 + ((plt_src.read_counter() - plt_stamp) & plt_mask); stamp = __read_platform_stime(count); stime_platform_stamp = stamp; platform_timer_stamp = count; - spin_unlock(&platform_timer_lock); + spin_unlock_irq(&platform_timer_lock); } static void resume_platform_timer(void) { - if ( platform_timer_is_tsc() ) - { - /* TODO: Save/restore TSC values. */ - return; - } - /* No change in platform_stime across suspend/resume. */ platform_timer_stamp = plt_stamp64; plt_stamp = plt_src.read_counter(); @@ -600,8 +568,6 @@ static void init_platform_timer(void) rc = init_cyclone(pts); else if ( !strcmp(opt_clocksource, "acpi") ) rc = init_pmtimer(pts); - else if ( !strcmp(opt_clocksource, "tsc") ) - rc = init_tsctimer(pts); if ( rc <= 0 ) printk("WARNING: %s clocksource '%s'.\n", @@ -614,12 +580,6 @@ static void init_platform_timer(void) !init_hpet(pts) && !init_pmtimer(pts) ) init_pit(pts); - - if ( platform_timer_is_tsc() ) - { - printk("Platform timer is TSC\n"); - return; - } plt_mask = (u64)~0ull >> (64 - pts->counter_bits); @@ -823,10 +783,6 @@ int cpu_frequency_change(u64 freq) struct cpu_time *t = &this_cpu(cpu_time); u64 curr_tsc; - /* Nothing to do if TSC is platform timer. Assume it is constant-rate. */ - if ( platform_timer_is_tsc() ) - return 0; - /* Sanity check: CPU frequency allegedly dropping below 1MHz? */ if ( freq < 1000000u ) { @@ -847,9 +803,11 @@ int cpu_frequency_change(u64 freq) local_irq_enable(); /* A full epoch should pass before we check for deviation. */ - set_timer(&t->calibration_timer, NOW() + EPOCH); if ( smp_processor_id() == 0 ) + { + set_timer(&calibration_timer, NOW() + EPOCH); platform_time_calibration(); + } return 0; } @@ -875,9 +833,20 @@ void do_settime(unsigned long secs, unsi rcu_read_unlock(&domlist_read_lock); } +/* Per-CPU communication between rendezvous IRQ and softirq handler. */ +struct cpu_calibration { + u64 local_tsc_stamp; + s_time_t stime_local_stamp; + s_time_t stime_master_stamp; + struct timer softirq_callback; +}; +static DEFINE_PER_CPU(struct cpu_calibration, cpu_calibration); + +/* Softirq handler for per-CPU time calibration. */ static void local_time_calibration(void *unused) { struct cpu_time *t = &this_cpu(cpu_time); + struct cpu_calibration *c = &this_cpu(cpu_calibration); /* * System timestamps, extrapolated from local and master oscillators, @@ -908,26 +877,15 @@ static void local_time_calibration(void /* The overall calibration scale multiplier. */ u32 calibration_mul_frac; - if ( platform_timer_is_tsc() ) - { - make_tsctimer_record(); - update_vcpu_system_time(current); - set_timer(&t->calibration_timer, NOW() + MILLISECS(10*1000)); - return; - } - prev_tsc = t->local_tsc_stamp; prev_local_stime = t->stime_local_stamp; prev_master_stime = t->stime_master_stamp; - /* - * Disable IRQs to get 'instantaneous' current timestamps. We read platform - * time first, as we may be delayed when acquiring platform_timer_lock. - */ + /* Disabling IRQs ensures we atomically read cpu_calibration struct. */ local_irq_disable(); - curr_master_stime = read_platform_stime(); - curr_local_stime = get_s_time(); - rdtscll(curr_tsc); + curr_tsc = c->local_tsc_stamp; + curr_local_stime = c->stime_local_stamp; + curr_master_stime = c->stime_master_stamp; local_irq_enable(); #if 0 @@ -1021,10 +979,62 @@ static void local_time_calibration(void update_vcpu_system_time(current); out: - set_timer(&t->calibration_timer, NOW() + EPOCH); - if ( smp_processor_id() == 0 ) + { + set_timer(&calibration_timer, NOW() + EPOCH); platform_time_calibration(); + } +} + +/* + * Rendezvous for all CPUs in IRQ context. + * Master CPU snapshots the platform timer. + * All CPUS snapshot their local TSC and extrapolation of system time. + */ +struct calibration_rendezvous { + atomic_t nr_cpus; + s_time_t master_stime; +}; + +static void time_calibration_rendezvous(void *_r) +{ + unsigned int total_cpus = num_online_cpus(); + struct cpu_calibration *c = &this_cpu(cpu_calibration); + struct calibration_rendezvous *r = _r; + + local_irq_disable(); + + if ( smp_processor_id() == 0 ) + { + while ( atomic_read(&r->nr_cpus) != (total_cpus - 1) ) + cpu_relax(); + r->master_stime = read_platform_stime(); + atomic_inc(&r->nr_cpus); + } + else + { + atomic_inc(&r->nr_cpus); + while ( atomic_read(&r->nr_cpus) != total_cpus ) + cpu_relax(); + } + + rdtscll(c->local_tsc_stamp); + c->stime_local_stamp = get_s_time(); + c->stime_master_stamp = r->master_stime; + + local_irq_enable(); + + /* Callback in softirq context as soon as possible. */ + set_timer(&c->softirq_callback, c->stime_local_stamp); +} + +static void time_calibration(void *unused) +{ + struct calibration_rendezvous r = { + .nr_cpus = ATOMIC_INIT(0) + }; + + on_each_cpu(time_calibration_rendezvous, &r, 0, 1); } void init_percpu_time(void) @@ -1032,12 +1042,6 @@ void init_percpu_time(void) struct cpu_time *t = &this_cpu(cpu_time); unsigned long flags; s_time_t now; - - if ( platform_timer_is_tsc() ) - { - make_tsctimer_record(); - goto out; - } local_irq_save(flags); rdtscll(t->local_tsc_stamp); @@ -1047,10 +1051,14 @@ void init_percpu_time(void) t->stime_master_stamp = now; t->stime_local_stamp = now; - out: - init_timer(&t->calibration_timer, local_time_calibration, - NULL, smp_processor_id()); - set_timer(&t->calibration_timer, NOW() + EPOCH); + init_timer(&this_cpu(cpu_calibration).softirq_callback, + local_time_calibration, NULL, smp_processor_id()); + + if ( smp_processor_id() == 0 ) + { + init_timer(&calibration_timer, time_calibration, NULL, 0); + set_timer(&calibration_timer, NOW() + EPOCH); + } } /* Late init function (after all CPUs are booted). */ @@ -1134,7 +1142,10 @@ void pit_broadcast_enter(void) void pit_broadcast_exit(void) { - cpu_clear(smp_processor_id(), pit_broadcast_mask); + int cpu = smp_processor_id(); + + if ( cpu_test_and_clear(cpu, pit_broadcast_mask) ) + reprogram_timer(per_cpu(timer_deadline, cpu)); } int pit_broadcast_is_available(void) @@ -1163,10 +1174,11 @@ int time_suspend(void) { cmos_utc_offset = -get_cmos_time(); cmos_utc_offset += (wc_sec + (wc_nsec + NOW()) / 1000000000ULL); + kill_timer(&calibration_timer); } /* Better to cancel calibration timer for accuracy. */ - kill_timer(&this_cpu(cpu_time).calibration_timer); + kill_timer(&this_cpu(cpu_calibration).softirq_callback); return 0; } diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/x86_64/physdev.c --- a/xen/arch/x86/x86_64/physdev.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/x86_64/physdev.c Thu Aug 07 11:57:34 2008 +0900 @@ -30,6 +30,15 @@ #define physdev_irq_status_query compat_physdev_irq_status_query #define physdev_irq_status_query_t physdev_irq_status_query_compat_t +#define physdev_map_pirq compat_physdev_map_pirq +#define physdev_map_pirq_t physdev_map_pirq_compat_t + +#define physdev_unmap_pirq compat_physdev_unmap_pirq +#define physdev_unmap_pirq_t physdev_unmap_pirq_compat_t + +#define physdev_manage_pci compat_physdev_manage_pci +#define physdev_manage_pci_t physdev_manage_pci_compat_t + #define COMPAT #undef guest_handle_okay #define guest_handle_okay compat_handle_okay diff -r 7affdebb7a1e -r a39913db6e51 xen/arch/x86/x86_emulate/x86_emulate.c --- a/xen/arch/x86/x86_emulate/x86_emulate.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/arch/x86/x86_emulate/x86_emulate.c Thu Aug 07 11:57:34 2008 +0900 @@ -1606,6 +1606,7 @@ x86_emulate( dst.val = _regs.eax; case 0x38 ... 0x3b: cmp: /* cmp */ emulate_2op_SrcV("cmp", src, dst, _regs.eflags); + dst.type = OP_NONE; break; case 0x62: /* bound */ { @@ -1707,6 +1708,7 @@ x86_emulate( dst.val = _regs.eax; case 0x84 ... 0x85: test: /* test */ emulate_2op_SrcV("test", src, dst, _regs.eflags); + dst.type = OP_NONE; break; case 0x86 ... 0x87: xchg: /* xchg */ diff -r 7affdebb7a1e -r a39913db6e51 xen/common/compat/grant_table.c --- a/xen/common/compat/grant_table.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/common/compat/grant_table.c Thu Aug 07 11:57:34 2008 +0900 @@ -138,7 +138,6 @@ int compat_grant_table_op(unsigned int c for ( i = 0; i < (_s_)->nr_frames; ++i ) \ { \ unsigned int frame = (_s_)->frame_list.p[i]; \ - BUG_ON(frame != (_s_)->frame_list.p[i]); \ (void)__copy_to_compat_offset((_d_)->frame_list, i, &frame, 1); \ } \ } \ diff -r 7affdebb7a1e -r a39913db6e51 xen/common/domain.c --- a/xen/common/domain.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/common/domain.c Thu Aug 07 11:57:34 2008 +0900 @@ -50,7 +50,7 @@ static void __init setup_cpufreq_option( else if ( !strcmp(str, "xen") ) { xen_processor_pmbits |= XEN_PROCESSOR_PM_PX; - cpufreq_controller = FREQCTL_none; + cpufreq_controller = FREQCTL_xen; } } custom_param("cpufreq", setup_cpufreq_option); @@ -136,6 +136,8 @@ struct vcpu *alloc_vcpu( v->runstate.state = is_idle_vcpu(v) ? RUNSTATE_running : RUNSTATE_offline; v->runstate.state_entry_time = NOW(); + + spin_lock_init(&v->virq_lock); if ( !is_idle_domain(d) ) { diff -r 7affdebb7a1e -r a39913db6e51 xen/common/event_channel.c --- a/xen/common/event_channel.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/common/event_channel.c Thu Aug 07 11:57:34 2008 +0900 @@ -386,14 +386,18 @@ static long __evtchn_close(struct domain break; case ECS_PIRQ: - if ( (rc = pirq_guest_unbind(d1, chn1->u.pirq)) == 0 ) - d1->pirq_to_evtchn[chn1->u.pirq] = 0; + pirq_guest_unbind(d1, chn1->u.pirq); + d1->pirq_to_evtchn[chn1->u.pirq] = 0; break; case ECS_VIRQ: for_each_vcpu ( d1, v ) - if ( v->virq_to_evtchn[chn1->u.virq] == port1 ) - v->virq_to_evtchn[chn1->u.virq] = 0; + { + if ( v->virq_to_evtchn[chn1->u.virq] != port1 ) + continue; + v->virq_to_evtchn[chn1->u.virq] = 0; + spin_barrier(&v->virq_lock); + } break; case ECS_IPI: @@ -447,6 +451,9 @@ static long __evtchn_close(struct domain BUG(); } + /* Clear pending event to avoid unexpected behavior on re-bind. */ + clear_bit(port1, &shared_info(d1, evtchn_pending)); + /* Reset binding to vcpu0 when the channel is freed. */ chn1->state = ECS_FREE; chn1->notify_vcpu_id = 0; @@ -573,37 +580,33 @@ static int evtchn_set_pending(struct vcp return 0; } +int guest_enabled_event(struct vcpu *v, int virq) +{ + return ((v != NULL) && (v->virq_to_evtchn[virq] != 0)); +} void send_guest_vcpu_virq(struct vcpu *v, int virq) { + unsigned long flags; int port; ASSERT(!virq_is_global(virq)); + + spin_lock_irqsave(&v->virq_lock, flags); port = v->virq_to_evtchn[virq]; if ( unlikely(port == 0) ) - return; + goto out; evtchn_set_pending(v, port); -} - -int guest_enabled_event(struct vcpu *v, int virq) -{ - int port; - - if ( unlikely(v == NULL) ) - return 0; - - port = v->virq_to_evtchn[virq]; - if ( port == 0 ) - return 0; - - /* virq is in use */ - return 1; + + out: + spin_unlock_irqrestore(&v->virq_lock, flags); } void send_guest_global_virq(struct domain *d, int virq) { + unsigned long flags; int port; struct vcpu *v; struct evtchn *chn; @@ -617,20 +620,28 @@ void send_guest_global_virq(struct domai if ( unlikely(v == NULL) ) return; + spin_lock_irqsave(&v->virq_lock, flags); + port = v->virq_to_evtchn[virq]; if ( unlikely(port == 0) ) - return; + goto out; chn = evtchn_from_port(d, port); evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); -} - + + out: + spin_unlock_irqrestore(&v->virq_lock, flags); +} int send_guest_pirq(struct domain *d, int pirq) { int port = d->pirq_to_evtchn[pirq]; struct evtchn *chn; + /* + * It should not be possible to race with __evtchn_close(): + * The caller of this function must synchronise with pirq_guest_unbind(). + */ ASSERT(port != 0); chn = evtchn_from_port(d, port); diff -r 7affdebb7a1e -r a39913db6e51 xen/common/keyhandler.c --- a/xen/common/keyhandler.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/common/keyhandler.c Thu Aug 07 11:57:34 2008 +0900 @@ -143,7 +143,7 @@ static void halt_machine(unsigned char k static void halt_machine(unsigned char key, struct cpu_user_regs *regs) { printk("'%c' pressed -> rebooting machine\n", key); - machine_restart(); + machine_restart(0); } static void cpuset_print(char *set, int size, cpumask_t mask) @@ -236,6 +236,7 @@ static void dump_domains(unsigned char k static cpumask_t read_clocks_cpumask = CPU_MASK_NONE; static s_time_t read_clocks_time[NR_CPUS]; +static u64 read_cycles_time[NR_CPUS]; static void read_clocks_slave(void *unused) { @@ -244,14 +245,20 @@ static void read_clocks_slave(void *unus while ( !cpu_isset(cpu, read_clocks_cpumask) ) cpu_relax(); read_clocks_time[cpu] = NOW(); + read_cycles_time[cpu] = get_cycles(); cpu_clear(cpu, read_clocks_cpumask); local_irq_enable(); } static void read_clocks(unsigned char key) { - unsigned int cpu = smp_processor_id(), min_cpu, max_cpu; - u64 min, max, dif, difus; + unsigned int cpu = smp_processor_id(), min_stime_cpu, max_stime_cpu; + unsigned int min_cycles_cpu, max_cycles_cpu; + u64 min_stime, max_stime, dif_stime; + u64 min_cycles, max_cycles, dif_cycles; + static u64 sumdif_stime = 0, maxdif_stime = 0; + static u64 sumdif_cycles = 0, maxdif_cycles = 0; + static u32 count = 0; static DEFINE_SPINLOCK(lock); spin_lock(&lock); @@ -261,31 +268,48 @@ static void read_clocks(unsigned char ke local_irq_disable(); read_clocks_cpumask = cpu_online_map; read_clocks_time[cpu] = NOW(); + read_cycles_time[cpu] = get_cycles(); cpu_clear(cpu, read_clocks_cpumask); local_irq_enable(); while ( !cpus_empty(read_clocks_cpumask) ) cpu_relax(); - min_cpu = max_cpu = cpu; + min_stime_cpu = max_stime_cpu = min_cycles_cpu = max_cycles_cpu = cpu; for_each_online_cpu ( cpu ) { - if ( read_clocks_time[cpu] < read_clocks_time[min_cpu] ) - min_cpu = cpu; - if ( read_clocks_time[cpu] > read_clocks_time[max_cpu] ) - max_cpu = cpu; - } - - min = read_clocks_time[min_cpu]; - max = read_clocks_time[max_cpu]; + if ( read_clocks_time[cpu] < read_clocks_time[min_stime_cpu] ) + min_stime_cpu = cpu; + if ( read_clocks_time[cpu] > read_clocks_time[max_stime_cpu] ) + max_stime_cpu = cpu; + if ( read_cycles_time[cpu] < read_cycles_time[min_cycles_cpu] ) + min_cycles_cpu = cpu; + if ( read_cycles_time[cpu] > read_cycles_time[max_cycles_cpu] ) + max_cycles_cpu = cpu; + } + + min_stime = read_clocks_time[min_stime_cpu]; + max_stime = read_clocks_time[max_stime_cpu]; + min_cycles = read_cycles_time[min_cycles_cpu]; + max_cycles = read_cycles_time[max_cycles_cpu]; spin_unlock(&lock); - dif = difus = max - min; - do_div(difus, 1000); - printk("Min = %"PRIu64" ; Max = %"PRIu64" ; Diff = %"PRIu64 - " (%"PRIu64" microseconds)\n", - min, max, dif, difus); + dif_stime = max_stime - min_stime; + if ( dif_stime > maxdif_stime ) + maxdif_stime = dif_stime; + sumdif_stime += dif_stime; + dif_cycles = max_cycles - min_cycles; + if ( dif_cycles > maxdif_cycles ) + maxdif_cycles = dif_cycles; + sumdif_cycles += dif_cycles; + count++; + printk("Synced stime skew: max=%"PRIu64"ns avg=%"PRIu64"ns " + "samples=%"PRIu32" current=%"PRIu64"ns\n", + maxdif_stime, sumdif_stime/count, count, dif_stime); + printk("Synced cycles skew: max=%"PRIu64" avg=%"PRIu64" " + "samples=%"PRIu32" current=%"PRIu64"\n", + maxdif_cycles, sumdif_cycles/count, count, dif_cycles); } extern void dump_runq(unsigned char key); diff -r 7affdebb7a1e -r a39913db6e51 xen/common/page_alloc.c --- a/xen/common/page_alloc.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/common/page_alloc.c Thu Aug 07 11:57:34 2008 +0900 @@ -53,34 +53,11 @@ boolean_param("bootscrub", opt_bootscrub boolean_param("bootscrub", opt_bootscrub); /* - * Bit width of the DMA heap. - */ -static unsigned int dma_bitsize = CONFIG_DMA_BITSIZE; -static void __init parse_dma_bits(char *s) -{ - unsigned int v = simple_strtol(s, NULL, 0); - if ( v >= (BITS_PER_LONG + PAGE_SHIFT) ) - dma_bitsize = BITS_PER_LONG + PAGE_SHIFT; - else if ( v > PAGE_SHIFT + 1 ) - dma_bitsize = v; - else - printk("Invalid dma_bits value of %u ignored.\n", v); -} -custom_param("dma_bits", parse_dma_bits); - -/* - * Amount of memory to reserve in a low-memory (<4GB) pool for specific - * allocation requests. Ordinary requests will not fall back to the - * lowmem emergency pool. - */ -static unsigned long dma_emergency_pool_pages; -static void __init parse_dma_emergency_pool(char *s) -{ - unsigned long long bytes; - bytes = parse_size_and_unit(s, NULL); - dma_emergency_pool_pages = bytes >> PAGE_SHIFT; -} -custom_param("dma_emergency_pool", parse_dma_emergency_pool); + * Bit width of the DMA heap -- used to override NUMA-node-first. + * allocation strategy, which can otherwise exhaust low memory. + */ +static unsigned int dma_bitsize; +integer_param("dma_bits", dma_bitsize); #define round_pgdown(_p) ((_p)&PAGE_MASK) #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) @@ -281,11 +258,7 @@ unsigned long __init alloc_boot_pages( */ #define MEMZONE_XEN 0 -#ifdef PADDR_BITS #define NR_ZONES (PADDR_BITS - PAGE_SHIFT) -#else -#define NR_ZONES (BITS_PER_LONG - PAGE_SHIFT) -#endif #define pfn_dom_zone_type(_pfn) (fls(_pfn) - 1) @@ -583,7 +556,22 @@ void __init end_boot_allocator(void) init_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 1); } - printk("Domain heap initialised: DMA width %u bits\n", dma_bitsize); + if ( !dma_bitsize && (num_online_nodes() > 1) ) + { +#ifdef CONFIG_X86 + dma_bitsize = min_t(unsigned int, + fls(NODE_DATA(0)->node_spanned_pages) - 1 + + PAGE_SHIFT - 2, + 32); +#else + dma_bitsize = 32; +#endif + } + + printk("Domain heap initialised"); + if ( dma_bitsize ) + printk(" DMA width %u bits", dma_bitsize); + printk("\n"); } #undef avail_for_domheap @@ -803,19 +791,9 @@ struct page_info *alloc_domheap_pages( if ( bits < zone_hi ) zone_hi = bits; - if ( (zone_hi + PAGE_SHIFT) >= dma_bitsize ) - { + if ( (dma_bitsize > PAGE_SHIFT) && + ((zone_hi + PAGE_SHIFT) >= dma_bitsize) ) pg = alloc_heap_pages(dma_bitsize - PAGE_SHIFT, zone_hi, node, order); - - /* Failure? Then check if we can fall back to the DMA pool. */ - if ( unlikely(pg == NULL) && - ((order > MAX_ORDER) || - (avail_heap_pages(MEMZONE_XEN + 1, - dma_bitsize - PAGE_SHIFT - 1, - -1) < - (dma_emergency_pool_pages + (1UL << order)))) ) - return NULL; - } if ( (pg == NULL) && ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi, @@ -917,28 +895,15 @@ unsigned long avail_domheap_pages_region unsigned long avail_domheap_pages(void) { - unsigned long avail_nrm, avail_dma; - - avail_nrm = avail_heap_pages(dma_bitsize - PAGE_SHIFT, - NR_ZONES - 1, - -1); - - avail_dma = avail_heap_pages(MEMZONE_XEN + 1, - dma_bitsize - PAGE_SHIFT - 1, - -1); - - if ( avail_dma > dma_emergency_pool_pages ) - avail_dma -= dma_emergency_pool_pages; - else - avail_dma = 0; - - return avail_nrm + avail_dma; + return avail_heap_pages(MEMZONE_XEN + 1, + NR_ZONES - 1, + -1); } static void pagealloc_keyhandler(unsigned char key) { unsigned int zone = MEMZONE_XEN; - unsigned long total = 0; + unsigned long n, total = 0; printk("Physical memory information:\n"); printk(" Xen heap: %lukB free\n", @@ -946,9 +911,7 @@ static void pagealloc_keyhandler(unsigne while ( ++zone < NR_ZONES ) { - unsigned long n; - - if ( zone == dma_bitsize - PAGE_SHIFT ) + if ( (zone + PAGE_SHIFT) == dma_bitsize ) { printk(" DMA heap: %lukB free\n", total << (PAGE_SHIFT-10)); total = 0; diff -r 7affdebb7a1e -r a39913db6e51 xen/common/shutdown.c --- a/xen/common/shutdown.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/common/shutdown.c Thu Aug 07 11:57:34 2008 +0900 @@ -23,8 +23,7 @@ static void maybe_reboot(void) { printk("rebooting machine in 5 seconds.\n"); watchdog_disable(); - mdelay(5000); - machine_restart(); + machine_restart(5000); } } @@ -50,7 +49,7 @@ void dom0_shutdown(u8 reason) case SHUTDOWN_reboot: { printk("Domain 0 shutdown: rebooting machine.\n"); - machine_restart(); + machine_restart(0); break; /* not reached */ } diff -r 7affdebb7a1e -r a39913db6e51 xen/drivers/char/console.c --- a/xen/drivers/char/console.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/drivers/char/console.c Thu Aug 07 11:57:34 2008 +0900 @@ -939,8 +939,7 @@ void panic(const char *fmt, ...) else { watchdog_disable(); - mdelay(5000); - machine_restart(); + machine_restart(5000); } } diff -r 7affdebb7a1e -r a39913db6e51 xen/drivers/passthrough/amd/iommu_acpi.c --- a/xen/drivers/passthrough/amd/iommu_acpi.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/drivers/passthrough/amd/iommu_acpi.c Thu Aug 07 11:57:34 2008 +0900 @@ -27,6 +27,7 @@ extern unsigned long amd_iommu_page_entr extern unsigned long amd_iommu_page_entries; extern unsigned short ivrs_bdf_entries; extern struct ivrs_mappings *ivrs_mappings; +extern unsigned short last_bdf; static struct amd_iommu * __init find_iommu_from_bdf_cap( u16 bdf, u8 cap_offset) @@ -85,10 +86,8 @@ static void __init reserve_unity_map_for } /* extend r/w permissioms and keep aggregate */ - if ( iw ) - ivrs_mappings[bdf].write_permission = IOMMU_CONTROL_ENABLED; - if ( ir ) - ivrs_mappings[bdf].read_permission = IOMMU_CONTROL_ENABLED; + ivrs_mappings[bdf].write_permission = iw; + ivrs_mappings[bdf].read_permission = ir; ivrs_mappings[bdf].unity_map_enable = IOMMU_CONTROL_ENABLED; ivrs_mappings[bdf].addr_range_start = base; ivrs_mappings[bdf].addr_range_length = length; @@ -112,7 +111,7 @@ static int __init register_exclusion_ran length = range_top - base; /* reserve r/w unity-mapped page entries for devices */ /* note: these entries are part of the exclusion range */ - for (bdf = 0; bdf < ivrs_bdf_entries; ++bdf) + for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ ) reserve_unity_map_for_device(bdf, base, length, iw, ir); /* push 'base' just outside of virtual address space */ base = iommu_top; @@ -190,7 +189,7 @@ static int __init register_exclusion_ran length = range_top - base; /* reserve r/w unity-mapped page entries for devices */ /* note: these entries are part of the exclusion range */ - for ( bdf = 0; bdf < ivrs_bdf_entries; ++bdf ) + for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ ) { bus = bdf >> 8; devfn = bdf & 0xFF; @@ -357,7 +356,7 @@ static u16 __init parse_ivhd_device_padd } static u16 __init parse_ivhd_device_select( - union acpi_ivhd_device *ivhd_device) + union acpi_ivhd_device *ivhd_device, struct amd_iommu *iommu) { u16 bdf; @@ -373,13 +372,14 @@ static u16 __init parse_ivhd_device_sele get_field_from_byte(ivhd_device->header.flags, AMD_IOMMU_ACPI_SYS_MGT_MASK, AMD_IOMMU_ACPI_SYS_MGT_SHIFT); + ivrs_mappings[bdf].iommu = iommu; return sizeof(struct acpi_ivhd_device_header); } static u16 __init parse_ivhd_device_range( union acpi_ivhd_device *ivhd_device, - u16 header_length, u16 block_length) + u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, first_bdf, last_bdf, bdf; u8 sys_mgt; @@ -423,14 +423,17 @@ static u16 __init parse_ivhd_device_rang AMD_IOMMU_ACPI_SYS_MGT_MASK, AMD_IOMMU_ACPI_SYS_MGT_SHIFT); for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) + { ivrs_mappings[bdf].dte_sys_mgt_enable = sys_mgt; + ivrs_mappings[bdf].iommu = iommu; + } return dev_length; } static u16 __init parse_ivhd_device_alias( union acpi_ivhd_device *ivhd_device, - u16 header_length, u16 block_length) + u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, alias_id, bdf; @@ -463,15 +466,18 @@ static u16 __init parse_ivhd_device_alia get_field_from_byte(ivhd_device->header.flags, AMD_IOMMU_ACPI_SYS_MGT_MASK, AMD_IOMMU_ACPI_SYS_MGT_SHIFT); + ivrs_mappings[bdf].iommu = iommu; + ivrs_mappings[alias_id].dte_sys_mgt_enable = ivrs_mappings[bdf].dte_sys_mgt_enable; + ivrs_mappings[alias_id].iommu = iommu; return dev_length; } static u16 __init parse_ivhd_device_alias_range( union acpi_ivhd_device *ivhd_device, - u16 header_length, u16 block_length) + u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, first_bdf, last_bdf, alias_id, bdf; @@ -527,15 +533,17 @@ static u16 __init parse_ivhd_device_alia { ivrs_mappings[bdf].dte_requestor_id = alias_id; ivrs_mappings[bdf].dte_sys_mgt_enable = sys_mgt; + ivrs_mappings[bdf].iommu = iommu; } ivrs_mappings[alias_id].dte_sys_mgt_enable = sys_mgt; + ivrs_mappings[alias_id].iommu = iommu; return dev_length; } static u16 __init parse_ivhd_device_extended( union acpi_ivhd_device *ivhd_device, - u16 header_length, u16 block_length) + u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, bdf; @@ -558,13 +566,14 @@ static u16 __init parse_ivhd_device_exte get_field_from_byte(ivhd_device->header.flags, AMD_IOMMU_ACPI_SYS_MGT_MASK, AMD_IOMMU_ACPI_SYS_MGT_SHIFT); + ivrs_mappings[bdf].iommu = iommu; return dev_length; } static u16 __init parse_ivhd_device_extended_range( union acpi_ivhd_device *ivhd_device, - u16 header_length, u16 block_length) + u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, first_bdf, last_bdf, bdf; u8 sys_mgt; @@ -609,7 +618,10 @@ static u16 __init parse_ivhd_device_exte AMD_IOMMU_ACPI_SYS_MGT_MASK, AMD_IOMMU_ACPI_SYS_MGT_SHIFT); for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) + { ivrs_mappings[bdf].dte_sys_mgt_enable = sys_mgt; + ivrs_mappings[bdf].iommu = iommu; + } return dev_length; } @@ -635,33 +647,6 @@ static int __init parse_ivhd_block(struc ivhd_block->header.dev_id, ivhd_block->cap_offset); return -ENODEV; } - - amd_iov_info("IVHD Block:\n"); - amd_iov_info(" Cap_Offset 0x%x\n", ivhd_block->cap_offset); - amd_iov_info(" MMIO_BAR_Phys 0x%"PRIx64"\n",ivhd_block->mmio_base); - amd_iov_info( " PCI_Segment 0x%x\n", ivhd_block->pci_segment); - amd_iov_info( " IOMMU_Info 0x%x\n", ivhd_block->iommu_info); - - /* override IOMMU support flags */ - iommu->coherent = get_field_from_byte(ivhd_block->header.flags, - AMD_IOMMU_ACPI_COHERENT_MASK, - AMD_IOMMU_ACPI_COHERENT_SHIFT); - iommu->iotlb_support = get_field_from_byte(ivhd_block->header.flags, - AMD_IOMMU_ACPI_IOTLB_SUP_MASK, - AMD_IOMMU_ACPI_IOTLB_SUP_SHIFT); - iommu->isochronous = get_field_from_byte(ivhd_block->header.flags, - AMD_IOMMU_ACPI_ISOC_MASK, - AMD_IOMMU_ACPI_ISOC_SHIFT); - iommu->res_pass_pw = get_field_from_byte(ivhd_block->header.flags, - AMD_IOMMU_ACPI_RES_PASS_PW_MASK, - AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT); - iommu->pass_pw = get_field_from_byte(ivhd_block->header.flags, - AMD_IOMMU_ACPI_PASS_PW_MASK, - AMD_IOMMU_ACPI_PASS_PW_SHIFT); - iommu->ht_tunnel_enable = get_field_from_byte( - ivhd_block->header.flags, - AMD_IOMMU_ACPI_HT_TUN_ENB_MASK, - AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT); /* parse Device Entries */ block_length = sizeof(struct acpi_ivhd_block_header); @@ -689,32 +674,32 @@ static int __init parse_ivhd_block(struc ivhd_block->header.length, block_length); break; case AMD_IOMMU_ACPI_IVHD_DEV_SELECT: - dev_length = parse_ivhd_device_select(ivhd_device); + dev_length = parse_ivhd_device_select(ivhd_device, iommu); break; case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START: dev_length = parse_ivhd_device_range( ivhd_device, - ivhd_block->header.length, block_length); + ivhd_block->header.length, block_length, iommu); break; case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT: dev_length = parse_ivhd_device_alias( ivhd_device, - ivhd_block->header.length, block_length); + ivhd_block->header.length, block_length, iommu); break; case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE: dev_length = parse_ivhd_device_alias_range( ivhd_device, - ivhd_block->header.length, block_length); + ivhd_block->header.length, block_length, iommu); break; case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT: dev_length = parse_ivhd_device_extended( ivhd_device, - ivhd_block->header.length, block_length); + ivhd_block->header.length, block_length, iommu); break; case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE: dev_length = parse_ivhd_device_extended_range( ivhd_device, - ivhd_block->header.length, block_length); + ivhd_block->header.length, block_length, iommu); break; default: amd_iov_error("IVHD Error: Invalid Device Type!\n"); @@ -794,29 +779,16 @@ static void __init dump_acpi_table_heade } -int __init parse_ivrs_table(struct acpi_table_header *_table) +static int __init parse_ivrs_table(struct acpi_table_header *_table) { struct acpi_ivrs_block_header *ivrs_block; - unsigned long length, i; - u8 checksum, *raw_table; + unsigned long length; int error = 0; struct acpi_table_header *table = (struct acpi_table_header *)_table; BUG_ON(!table); dump_acpi_table_header(table); - - /* validate checksum: sum of entire table == 0 */ - checksum = 0; - raw_table = (u8 *)table; - for ( i = 0; i < table->length; i++ ) - checksum += raw_table[i]; - if ( checksum ) - { - amd_iov_error("IVRS Error: " - "Invalid Checksum 0x%x\n", checksum); - return -ENODEV; - } /* parse IVRS blocks */ length = sizeof(struct acpi_ivrs_table_header); @@ -846,3 +818,144 @@ int __init parse_ivrs_table(struct acpi_ return error; } + +static int __init detect_iommu_acpi(struct acpi_table_header *_table) +{ + struct acpi_ivrs_block_header *ivrs_block; + struct acpi_table_header *table = (struct acpi_table_header *)_table; + unsigned long i; + unsigned long length = sizeof(struct acpi_ivrs_table_header); + u8 checksum, *raw_table; + + /* validate checksum: sum of entire table == 0 */ + checksum = 0; + raw_table = (u8 *)table; + for ( i = 0; i < table->length; i++ ) + checksum += raw_table[i]; + if ( checksum ) + { + amd_iov_error("IVRS Error: " + "Invalid Checksum 0x%x\n", checksum); + return -ENODEV; + } + + while ( table->length > (length + sizeof(*ivrs_block)) ) + { + ivrs_block = (struct acpi_ivrs_block_header *) ((u8 *)table + length); + if ( table->length < (length + ivrs_block->length) ) + return -ENODEV; + if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE ) + if ( amd_iommu_detect_one_acpi((void*)ivrs_block) != 0 ) + return -ENODEV; + length += ivrs_block->length; + } + return 0; +} + +#define UPDATE_LAST_BDF(x) do {\ + if ((x) > last_bdf) \ + last_bdf = (x); \ + } while(0); + +static int __init get_last_bdf_ivhd(void *ivhd) +{ + union acpi_ivhd_device *ivhd_device; + u16 block_length, dev_length; + struct acpi_ivhd_block_header *ivhd_block; + + ivhd_block = (struct acpi_ivhd_block_header *)ivhd; + + if ( ivhd_block->header.length < + sizeof(struct acpi_ivhd_block_header) ) + { + amd_iov_error("IVHD Error: Invalid Block Length!\n"); + return -ENODEV; + } + + block_length = sizeof(struct acpi_ivhd_block_header); + while ( ivhd_block->header.length >= + (block_length + sizeof(struct acpi_ivhd_device_header)) ) + { + ivhd_device = (union acpi_ivhd_device *) + ((u8 *)ivhd_block + block_length); + + switch ( ivhd_device->header.type ) + { + case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD: + dev_length = sizeof(u32); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD: + dev_length = sizeof(u64); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_SELECT: + UPDATE_LAST_BDF(ivhd_device->header.dev_id); + dev_length = sizeof(struct acpi_ivhd_device_header); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT: + UPDATE_LAST_BDF(ivhd_device->header.dev_id); + dev_length = sizeof(struct acpi_ivhd_device_alias); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT: + UPDATE_LAST_BDF(ivhd_device->header.dev_id); + dev_length = sizeof(struct acpi_ivhd_device_extended); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START: + UPDATE_LAST_BDF(ivhd_device->range.trailer.dev_id); + dev_length = sizeof(struct acpi_ivhd_device_range); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE: + UPDATE_LAST_BDF(ivhd_device->alias_range.trailer.dev_id) + dev_length = sizeof(struct acpi_ivhd_device_alias_range); + break; + case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE: + UPDATE_LAST_BDF(ivhd_device->extended_range.trailer.dev_id) + dev_length = sizeof(struct acpi_ivhd_device_extended_range); + break; + default: + amd_iov_error("IVHD Error: Invalid Device Type!\n"); + dev_length = 0; + break; + } + + block_length += dev_length; + if ( !dev_length ) + return -ENODEV; + } + + return 0; +} + +static int __init get_last_bdf_acpi(struct acpi_table_header *_table) +{ + struct acpi_ivrs_block_header *ivrs_block; + struct acpi_table_header *table = (struct acpi_table_header *)_table; + unsigned long length = sizeof(struct acpi_ivrs_table_header); + + while ( table->length > (length + sizeof(*ivrs_block)) ) + { + ivrs_block = (struct acpi_ivrs_block_header *) ((u8 *)table + length); + if ( table->length < (length + ivrs_block->length) ) + return -ENODEV; + if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE ) + if ( get_last_bdf_ivhd((void*)ivrs_block) != 0 ) + return -ENODEV; + length += ivrs_block->length; + } + return 0; +} + +int __init amd_iommu_detect_acpi(void) +{ + return acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, detect_iommu_acpi); +} + +int __init amd_iommu_get_ivrs_dev_entries(void) +{ + acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, get_last_bdf_acpi); + return last_bdf + 1; +} + +int __init amd_iommu_update_ivrs_mapping_acpi(void) +{ + return acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, parse_ivrs_table); +} diff -r 7affdebb7a1e -r a39913db6e51 xen/drivers/passthrough/amd/iommu_detect.c --- a/xen/drivers/passthrough/amd/iommu_detect.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/drivers/passthrough/amd/iommu_detect.c Thu Aug 07 11:57:34 2008 +0900 @@ -25,65 +25,10 @@ #include <xen/pci_regs.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> +#include <asm/hvm/svm/amd-iommu-acpi.h> -static int __init valid_bridge_bus_config( - int bus, int dev, int func, int *sec_bus, int *sub_bus) -{ - int pri_bus; - - pri_bus = pci_conf_read8(bus, dev, func, PCI_PRIMARY_BUS); - *sec_bus = pci_conf_read8(bus, dev, func, PCI_SECONDARY_BUS); - *sub_bus = pci_conf_read8(bus, dev, func, PCI_SUBORDINATE_BUS); - - return ((pri_bus == bus) && (*sec_bus > bus) && (*sub_bus >= *sec_bus)); -} - -int __init get_iommu_last_downstream_bus(struct amd_iommu *iommu) -{ - int bus, dev, func; - int devfn, hdr_type; - int sec_bus, sub_bus; - int multi_func; - - bus = iommu->last_downstream_bus = iommu->root_bus; - iommu->downstream_bus_present[bus] = 1; - dev = PCI_SLOT(iommu->first_devfn); - multi_func = PCI_FUNC(iommu->first_devfn) > 0; - for ( devfn = iommu->first_devfn; devfn <= iommu->last_devfn; devfn++ ) - { - /* skipping to next device#? */ - if ( dev != PCI_SLOT(devfn) ) - { - dev = PCI_SLOT(devfn); - multi_func = 0; - } - func = PCI_FUNC(devfn); - - if ( !VALID_PCI_VENDOR_ID(pci_conf_read16(bus, dev, func, - PCI_VENDOR_ID)) ) - continue; - - hdr_type = pci_conf_read8(bus, dev, func, PCI_HEADER_TYPE); - if ( func == 0 ) - multi_func = IS_PCI_MULTI_FUNCTION(hdr_type); - - if ( (func == 0 || multi_func) && - IS_PCI_TYPE1_HEADER(hdr_type) ) - { - if ( !valid_bridge_bus_config(bus, dev, func, - &sec_bus, &sub_bus) ) - return -ENODEV; - - if ( sub_bus > iommu->last_downstream_bus ) - iommu->last_downstream_bus = sub_bus; - do { - iommu->downstream_bus_present[sec_bus] = 1; - } while ( sec_bus++ < sub_bus ); - } - } - - return 0; -} +extern struct list_head amd_iommu_head; +unsigned short last_bdf = 0; static int __init get_iommu_msi_capabilities(u8 bus, u8 dev, u8 func, struct amd_iommu *iommu) @@ -128,30 +73,10 @@ int __init get_iommu_capabilities(u8 bus struct amd_iommu *iommu) { u32 cap_header, cap_range, misc_info; - u64 mmio_bar; - - mmio_bar = (u64)pci_conf_read32( - bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32; - mmio_bar |= pci_conf_read32(bus, dev, func, - cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET); - iommu->mmio_base_phys = mmio_bar & (u64)~0x3FFF; - - if ( ((mmio_bar & 0x1) == 0) || (iommu->mmio_base_phys == 0) ) - { - amd_iov_error("Invalid MMIO_BAR = 0x%"PRIx64"\n", mmio_bar); - return -ENODEV; - } - - iommu->bdf = (bus << 8) | PCI_DEVFN(dev, func); - iommu->cap_offset = cap_ptr; cap_header = pci_conf_read32(bus, dev, func, cap_ptr); iommu->revision = get_field_from_reg_u32( cap_header, PCI_CAP_REV_MASK, PCI_CAP_REV_SHIFT); - iommu->iotlb_support = get_field_from_reg_u32( - cap_header, PCI_CAP_IOTLB_MASK, PCI_CAP_IOTLB_SHIFT); - iommu->ht_tunnel_support = get_field_from_reg_u32( - cap_header, PCI_CAP_HT_TUNNEL_MASK, PCI_CAP_HT_TUNNEL_SHIFT); iommu->pte_not_present_cached = get_field_from_reg_u32( cap_header, PCI_CAP_NP_CACHE_MASK, PCI_CAP_NP_CACHE_SHIFT); @@ -159,96 +84,76 @@ int __init get_iommu_capabilities(u8 bus cap_ptr + PCI_CAP_RANGE_OFFSET); iommu->unit_id = get_field_from_reg_u32( cap_range, PCI_CAP_UNIT_ID_MASK, PCI_CAP_UNIT_ID_SHIFT); - iommu->root_bus = get_field_from_reg_u32( - cap_range, PCI_CAP_BUS_NUMBER_MASK, PCI_CAP_BUS_NUMBER_SHIFT); - iommu->first_devfn = get_field_from_reg_u32( - cap_range, PCI_CAP_FIRST_DEVICE_MASK, PCI_CAP_FIRST_DEVICE_SHIFT); - iommu->last_devfn = get_field_from_reg_u32( - cap_range, PCI_CAP_LAST_DEVICE_MASK, PCI_CAP_LAST_DEVICE_SHIFT); misc_info = pci_conf_read32(bus, dev, func, cap_ptr + PCI_MISC_INFO_OFFSET); iommu->msi_number = get_field_from_reg_u32( misc_info, PCI_CAP_MSI_NUMBER_MASK, PCI_CAP_MSI_NUMBER_SHIFT); + return 0; +} + +int __init amd_iommu_detect_one_acpi(void *ivhd) +{ + struct amd_iommu *iommu; + u8 bus, dev, func; + struct acpi_ivhd_block_header *ivhd_block; + + ivhd_block = (struct acpi_ivhd_block_header *)ivhd; + + if ( ivhd_block->header.length < sizeof(struct acpi_ivhd_block_header) ) + { + amd_iov_error("Invalid IVHD Block Length!\n"); + return -ENODEV; + } + + if ( !ivhd_block->header.dev_id || + !ivhd_block->cap_offset || !ivhd_block->mmio_base) + { + amd_iov_error("Invalid IVHD Block!\n"); + return -ENODEV; + } + + iommu = (struct amd_iommu *) xmalloc(struct amd_iommu); + if ( !iommu ) + { + amd_iov_error("Error allocating amd_iommu\n"); + return -ENOMEM; + } + memset(iommu, 0, sizeof(struct amd_iommu)); + + spin_lock_init(&iommu->lock); + + iommu->bdf = ivhd_block->header.dev_id; + iommu->cap_offset = ivhd_block->cap_offset; + iommu->mmio_base_phys = ivhd_block->mmio_base; + + /* override IOMMU support flags */ + iommu->coherent = get_field_from_byte(ivhd_block->header.flags, + AMD_IOMMU_ACPI_COHERENT_MASK, + AMD_IOMMU_ACPI_COHERENT_SHIFT); + iommu->iotlb_support = get_field_from_byte(ivhd_block->header.flags, + AMD_IOMMU_ACPI_IOTLB_SUP_MASK, + AMD_IOMMU_ACPI_IOTLB_SUP_SHIFT); + iommu->isochronous = get_field_from_byte(ivhd_block->header.flags, + AMD_IOMMU_ACPI_ISOC_MASK, + AMD_IOMMU_ACPI_ISOC_SHIFT); + iommu->res_pass_pw = get_field_from_byte(ivhd_block->header.flags, + AMD_IOMMU_ACPI_RES_PASS_PW_MASK, + AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT); + iommu->pass_pw = get_field_from_byte(ivhd_block->header.flags, + AMD_IOMMU_ACPI_PASS_PW_MASK, + AMD_IOMMU_ACPI_PASS_PW_SHIFT); + iommu->ht_tunnel_enable = get_field_from_byte(ivhd_block->header.flags, + AMD_IOMMU_ACPI_HT_TUN_ENB_MASK, + AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT); + bus = iommu->bdf >> 8; + dev = PCI_SLOT(iommu->bdf & 0xFF); + func = PCI_FUNC(iommu->bdf & 0xFF); + get_iommu_capabilities(bus, dev, func, iommu->cap_offset, iommu); get_iommu_msi_capabilities(bus, dev, func, iommu); + + list_add_tail(&iommu->list, &amd_iommu_head); return 0; } - -static int __init scan_caps_for_iommu( - int bus, int dev, int func, - iommu_detect_callback_ptr_t iommu_detect_callback) -{ - int cap_ptr, cap_id, cap_type; - u32 cap_header; - int count, error = 0; - - count = 0; - cap_ptr = pci_conf_read8(bus, dev, func, PCI_CAPABILITY_LIST); - while ( (cap_ptr >= PCI_MIN_CAP_OFFSET) && - (count < PCI_MAX_CAP_BLOCKS) && - !error ) - { - cap_ptr &= PCI_CAP_PTR_MASK; - cap_header = pci_conf_read32(bus, dev, func, cap_ptr); - cap_id = get_field_from_reg_u32( - cap_header, PCI_CAP_ID_MASK, PCI_CAP_ID_SHIFT); - - if ( cap_id == PCI_CAP_ID_SECURE_DEVICE ) - { - cap_type = get_field_from_reg_u32( - cap_header, PCI_CAP_TYPE_MASK, PCI_CAP_TYPE_SHIFT); - if ( cap_type == PCI_CAP_TYPE_IOMMU ) - error = iommu_detect_callback( - bus, dev, func, cap_ptr); - } - - cap_ptr = get_field_from_reg_u32( - cap_header, PCI_CAP_NEXT_PTR_MASK, PCI_CAP_NEXT_PTR_SHIFT); - count++; - } - - return error; -} - -static int __init scan_functions_for_iommu( - int bus, int dev, iommu_detect_callback_ptr_t iommu_detect_callback) -{ - int func, hdr_type; - int count = 1, error = 0; - - for ( func = 0; - (func < count) && !error && - VALID_PCI_VENDOR_ID(pci_conf_read16(bus, dev, func, - PCI_VENDOR_ID)); - func++ ) - - { - hdr_type = pci_conf_read8(bus, dev, func, PCI_HEADER_TYPE); - - if ( (func == 0) && IS_PCI_MULTI_FUNCTION(hdr_type) ) - count = PCI_MAX_FUNC_COUNT; - - if ( IS_PCI_TYPE0_HEADER(hdr_type) || - IS_PCI_TYPE1_HEADER(hdr_type) ) - error = scan_caps_for_iommu(bus, dev, func, - iommu_detect_callback); - } - - return error; -} - - -int __init scan_for_iommu(iommu_detect_callback_ptr_t iommu_detect_callback) -{ - int bus, dev, error = 0; - - for ( bus = 0; bus < PCI_MAX_BUS_COUNT && !error; ++bus ) - for ( dev = 0; dev < PCI_MAX_DEV_COUNT && !error; ++dev ) - error = scan_functions_for_iommu(bus, dev, - iommu_detect_callback); - - return error; -} - diff -r 7affdebb7a1e -r a39913db6e51 xen/drivers/passthrough/amd/iommu_init.c --- a/xen/drivers/passthrough/amd/iommu_init.c Thu Aug 07 11:47:34 2008 +0900 +++ b/xen/drivers/passthrough/amd/iommu_init.c Thu Aug 07 11:57:34 2008 +0900 @@ -27,10 +27,20 @@ #include <asm/hvm/svm/amd-iommu-proto.h> #include <asm-x86/fixmap.h> -extern int nr_amd_iommus; static struct amd_iommu *vector_to_iommu[NR_VECTORS]; - -int __init map_iommu_mmio_region(struct amd_iommu *iommu) +static int nr_amd_iommus; +static long amd_iommu_cmd_buffer_entries = IOMMU_CMD_BUFFER_DEFAULT_ENTRIES; +static long amd_iommu_event_log_entries = IOMMU_EVENT_LOG_DEFAULT_ENTRIES; + +unsigned short ivrs_bdf_entries; +struct ivrs_mappings *ivrs_mappings; +struct list_head amd_iommu_head; +struct table_struct device_table; + +extern void *int_remap_table; +extern spinlock_t int_remap_table_lock; + +static int __init map_iommu_mmio_region(struct amd_iommu *iommu) { unsigned long mfn; @@ -51,7 +61,7 @@ int __init map_iommu_mmio_region(struct return 0; } -void __init unmap_iommu_mmio_region(struct amd_iommu *iommu) +static void __init unmap_iommu_mmio_region(struct amd_iommu *iommu) { if ( iommu->mmio_base ) { @@ -60,7 +70,7 @@ void __init unmap_iommu_mmio_region(stru } } -void __init register_iommu_dev_table_in_mmio_space(struct amd_iommu *iommu) +static void __init register_iommu_dev_table_in_mmio_space(struct amd_iommu *iommu) { u64 addr_64, addr_lo, addr_hi; u32 entry; @@ -83,7 +93,7 @@ void __init register_iommu_dev_table_in_ writel(entry, iommu->mmio_base + IOMMU_DEV_TABLE_BASE_HIGH_OFFSET); } -void __init register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu) +static void __init register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu) { u64 addr_64, addr_lo, addr_hi; u32 power_of2_entries; @@ -110,7 +120,7 @@ void __init register_iommu_cmd_buffer_in writel(entry, iommu->mmio_base+IOMMU_CMD_BUFFER_BASE_HIGH_OFFSET); } -void __init register_iommu_event_log_in_mmio_space(struct amd_iommu *iommu) +static void __init register_iommu_event_log_in_mmio_space(struct amd_iommu *iommu) { u64 addr_64, addr_lo, addr_hi; u32 power_of2_entries; @@ -266,12 +276,13 @@ static int amd_iommu_read_event_log(stru return -EFAULT; } -static void amd_iommu_msi_data_init(struct amd_iommu *iommu, int vector) +static void amd_iommu_msi_data_init(struct amd_iommu *iommu) { u32 msi_data; u8 bus = (iommu->bdf >> 8) & 0xff; u8 dev = PCI_SLOT(iommu->bdf & 0xff); u8 func = PCI_FUNC(iommu->bdf & 0xff); + int vector = iommu->vector; msi_data = MSI_DATA_TRIGGER_EDGE | MSI_DATA_LEVEL_ASSERT | @@ -434,7 +445,6 @@ static int set_iommu_interrupt_handler(s static int set_iommu_interrupt_handler(struct amd_iommu *iommu) { int vector, ret; - unsigned long flags; vector = assign_irq_vector(AUTO_ASSIGN); vector_to_iommu[vector] = iommu; @@ -450,38 +460,210 @@ static int set_iommu_interrupt_handler(s } irq_desc[vector].handler = &iommu_msi_type; - ret = request_irq(vector, amd_iommu_page_fault, 0, "dmar", iommu); + ret = request_irq(vector, amd_iommu_page_fault, 0, "amd_iommu", iommu); if ( ret ) { amd_iov_error("can't request irq\n"); return 0; } + return vector; +} + +void __init enable_iommu(struct amd_iommu *iommu) +{ + unsigned long flags; + spin_lock_irqsave(&iommu->lock, flags); - amd_iommu_msi_data_init (iommu, vector); + if ( iommu->enabled ) + { + spin_unlock_irqrestore(&iommu->lock, flags); + return; + } + + iommu->dev_table.alloc_size = device_table.alloc_size; + iommu->dev_table.entries = device_table.entries; + iommu->dev_table.buffer = device_table.buffer; + + register_iommu_dev_table_in_mmio_space(iommu); + register_iommu_cmd_buffer_in_mmio_space(iommu); + register_iommu_event_log_in_mmio_space(iommu); + register_iommu_exclusion_range(iommu); + + amd_iommu_msi_data_init (iommu); amd_iommu_msi_addr_init(iommu, cpu_physical_id(first_cpu(cpu_online_map))); amd_iommu_msi_enable(iommu, IOMMU_CONTROL_ENABLED); - spin_unlock_irqrestore(&iommu->lock, flags); - - return vector; -} - -void __init enable_iommu(struct amd_iommu *iommu) -{ - unsigned long flags; - - set_iommu_interrupt_handler(iommu); - - spin_lock_irqsave(&iommu->lock, flags); - - register_iommu_exclusion_range(iommu); set_iommu_command_buffer_control(iommu, IOMMU_CONTROL_ENABLED); set_iommu_event_log_control(iommu, IOMMU_CONTROL_ENABLED); set_iommu_translation_control(iommu, IOMMU_CONTROL_ENABLED); + printk("AMD_IOV: IOMMU %d Enabled.\n", nr_amd_iommus ); + nr_amd_iommus++; + + iommu->enabled = 1; spin_unlock_irqrestore(&iommu->lock, flags); - printk("AMD_IOV: IOMMU %d Enabled.\n", nr_amd_iommus); -} +} + +static void __init deallocate_iommu_table_struct( + struct table_struct *table) +{ + if ( table->buffer ) + { + free_xenheap_pages(table->buffer, + get_order_from_bytes(table->alloc_size)); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |